OC IOS 文件解压缩预览

热很。。热很。。。。夏天的城市只有热浪没有情怀。。。

来吧,come on。。。

引用第三方库:

pod 'SSZipArchive'

开发实现:

一、控制器实现

头文件控制器定义:

objectivec 复制代码
//
//  ZipRarViewController.h
//
//  Created by carbonzhao on 2024/5/28.
//

#import "IMBaseClassViewController.h"

NS_ASSUME_NONNULL_BEGIN

@interface ZipRarViewController : IMBaseClassViewController

//可为本地路径,亦可为远端路径
@property (nonatomic,strong) NSURL *filePath;

//路径标记,相同标记解压过的不再解压
@property (nonatomic,strong) NSString *fileFlag;

@end

NS_ASSUME_NONNULL_END

实现文件定义:

objectivec 复制代码
//
//  ZipRarViewController.m
//
//  Created by carbonzhao on 2024/5/28.
//

#import "ZipRarViewController.h"
#import "SSZipArchive.h"
#import "UIBreadView.h"

NS_ASSUME_NONNULL_BEGIN

@interface UINextTreeView : UIView
{
}
- (void)setDataSource:(NSMutableArray*)list checkActionBlock:(void (^)(NSDictionary *e))checkActionBlock;
@end

NS_ASSUME_NONNULL_END

typedef void (^SubTreeViewCheckedTreeBlock)(NSDictionary *e);

@interface UINextTreeView ()<UITableViewDelegate,UITableViewDataSource>
{
    NSMutableArray *dataList;
    UITableView *tview;
}
@property (nonatomic,copy) SubTreeViewCheckedTreeBlock ClickTreeBlock;
@end

@implementation UINextTreeView

- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame])
    {
        [self setupUI];
    }
    return self;
}


- (void)setFrame:(CGRect)frame
{
    [super setFrame:frame];
    if (tview)
    {
        [tview setFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
    }
}


- (void)setupUI
{
    dataList = [[NSMutableArray alloc] initWithCapacity:0];
    
    tview = [[UITableView alloc] initWithFrame:self.bounds];
    tview.backgroundColor = DSTextPlaceColor;
    tview.dataSource = self;
    tview.delegate = self;
//    tview.tableFooterView = [UIView new];
    tview.separatorColor = [UIColor clearColor];
    tview.estimatedRowHeight = 0;
    tview.estimatedSectionFooterHeight = 0;
    tview.estimatedSectionHeaderHeight = 0;
    [tview setShowsVerticalScrollIndicator:NO];
    [tview setShowsHorizontalScrollIndicator:NO];
//    [tview setBackgroundColor:[UIColor redColor]];
//    tview.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
//        [weakSelf getListAllDing:@"refresh"];
//    }];
    
    [self addSubview:tview];
}

#pragma mark - action
- (void)setDataSource:(NSMutableArray*)list checkActionBlock:(void (^)(NSDictionary *e))checkActionBlock
{
    [self setClickTreeBlock:checkActionBlock];
    [dataList addObjectsFromArray:list];
    [tview reloadData];
}


- (void)reloadView
{
    dispatch_async(dispatch_get_main_queue(), ^{
        [self->tview reloadData];
    });
}


- (NSString *)docIcon:(NSString *)ext
{
    NSString *ex = [ext lowercaseString];
    if ([@[@"xls",@"xlsx"] containsObject:ex])
    {
        return @"icon_excel_new";
    }
    else if ([@[@"doc",@"docx"] containsObject:ex])
    {
        return @"icon_word_new";
    }
    else if ([@[@"pdf"] containsObject:ex])
    {
        return @"icon_pdf_new";
    }
    else if ([@[@"txt"] containsObject:ex])
    {
        return @"icon_txt_new";
    }
    else if ([@[@"png",@"jpg",@"jpeg"] containsObject:ex])
    {
        return @"icon_img_new";
    }
    else if ([@[@"mov",@"mp4",@"avi",@"mpeg",@"mkv",@"3gp",@"wmv",@"rmvb"] containsObject:ex])
    {
        return @"icon_mp4_new";
    }
    else if ([@[@"mp3",@"wav"] containsObject:ex])
    {
        return @"icon_mp3";
    }
    else if ([@[@"zip",@"rar"] containsObject:ex])
    {
        return @"icon_zip_new";
    }
    return @"";
}

#pragma mark - tableView
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return dataList.count;
}



- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CGFloat height = 58;
    return height;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
    CGFloat height = [self tableView:tableView heightForRowAtIndexPath:indexPath];
    if (height > 0)
    {
        CGFloat x = 20;
        NSMutableDictionary *e = [dataList objectAtIndex:indexPath.row];
        
        kWeakSelf(self)
        NSString *dicon = [e boolForKey:@"isDir"]?@"icon_folder_icon":[self docIcon:[e stringForKey:@"ext"]];
        CGRect rt = CGRectMake(x, (height-30)/2, 30, 30);
        UIImageView *dirIcon = [[UIImageView alloc] initWithFrame:rt];
        [dirIcon setImage:IMAGE_INIM_NAME(dicon)];
        [cell.contentView addSubview:dirIcon];
        
        x += (rt.size.width + 10);
        NSString *name = [e stringForKey:@"fileName"];
        rt = CGRectMake(x, 0, tableView.frame.size.width-20-x-40, height);
        UILabel *label = [[UILabel alloc] initWithFrame:rt];
        [label setFont:Font_size(16)];
        [label setTextColor:RGBA(10, 10, 10, 1)];
        [label setText:name];
        [label setTextAlignment:NSTextAlignmentLeft];
        [cell.contentView addSubview:label];
        
        if ([e boolForKey:@"isDir"])
        {
            rt = CGRectMake(tableView.width-34, (height-14)/2, 14, 14);
            UIImageView *iconView = [[UIImageView alloc] initWithFrame:rt];
            [iconView setImage:IMAGE_INIM_NAME(@"icon_arrow")];
            [cell.contentView addSubview:iconView];
        }
        rt = CGRectMake(25, height-1, tableView.frame.size.width-25, 1);
        UIImageView *iconView = [[UIImageView alloc] initWithFrame:rt];
        [iconView setBackgroundColor:RGB(245, 245, 245)];
        [cell.contentView addSubview:iconView];
        
        rt = CGRectMake(0, 0, tableView.frame.size.width, height);
        iconView = [[UIImageView alloc] initWithFrame:rt];
        [iconView setBackgroundColor:RGB(245, 245, 245)];
        [cell setSelectedBackgroundView:iconView];
    }
    [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
    return cell;
}
        
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    
    NSMutableDictionary *e = [dataList objectAtIndex:indexPath.row];
    self.ClickTreeBlock(e);
}
@end

@interface ZipRarViewController ()
@property (nonatomic,strong) UIBreadView *breview;
@end

@implementation ZipRarViewController

- (instancetype)init
{
    if (self = [super init])
    {
        
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.breview = [UIBreadView breadViewWithFrame:CGRectMake(0, 0, ScreenWidth, self.safeAreaHeight) viewType:UIBreadViewBreadType];
    [self.view addSubview:self.breview];
    
    NSString *fileName = [self.filePath lastPathComponent]; //获取文件名称
    [self setTitle:[NSString stringWithFormat:@"%@预览",fileName]];
    if ([self.filePath.absoluteString hasPrefix:@"http"])
    {
        WeakSelf(self);
        [self showToastWithKeepAliveBlock:^(UIToastFenceView *waitView) {
            [waitView setViewMode:UIToastFenceViewModeCircle];
            [waitView setTitleText:@"下载中..."];
            
            NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
            
            AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
            NSURLRequest *request = [NSURLRequest requestWithURL:self.filePath];
            
            NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:^(NSProgress *downloadProgress){
                
                CGFloat completedUnitCount = downloadProgress.completedUnitCount*1.0;
                CGFloat totalUnitCount = downloadProgress.totalUnitCount*1.0;
                CGFloat percent = completedUnitCount/totalUnitCount;
                
                [waitView setProgress:percent];
                if (percent == 1.0)
                {
                    [waitView setViewMode:UIToastFenceViewModeText];
                    [waitView setTitleText:@"下载完成"];
                    [waitView dismiss:1.5];
                }
            } destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
                NSURL *url = [NSURL fileURLWithPath:userDocuments(@"docPathFile", fileName)];
                return url;
                
            } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
                if (error) {
                    [waitView setViewMode:UIToastFenceViewModeText];
                    [waitView setTitleText:@"下载失败"];
                    [waitView dismiss:1.5];
                }
                else 
                {
                    [waitView dismiss];
                    NSURL *url = [NSURL fileURLWithPath:userDocuments(@"docPathFile", fileName)];
                    weakSelf.filePath = url;
                    [weakSelf toReadySource];
                }
            }];
            [downloadTask resume];
        }];
    }
    else
    {
        [self toReadySource];
    }
}

#pragma mark - 解压文件
- (void)toReadySource
{
    NSString *path = [self.filePath path];
    NSString *fileName = [[[self.filePath lastPathComponent] componentsSeparatedByString:@"."] firstObject];
    NSString *to = userDocuments(@"zipsPathFile", @"");
    to = [to stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_%@",self.fileFlag,fileName]];
    
    WeakSelf(self);
//    [[NSFileManager defaultManager] removeItemAtPath:to error:nil];
    if ([[NSFileManager defaultManager] fileExistsAtPath:to])
    {
        [self showToastBlock:^(UIToastFenceView *waitView) {
            
            [weakSelf readFiles:[to stringByAppendingPathComponent:fileName] fileName:fileName];
        }];
    }
    else
    {
        [self showToastBlock:^(UIToastFenceView *waitView)
        {
            [waitView setTitleText:@"解压中..."];
            BOOL flag = [SSZipArchive unzipFileAtPath:path toDestination:to];
            if (flag)
            {
                [weakSelf readFiles:[to stringByAppendingPathComponent:fileName] fileName:fileName];
            }
            else
            {
                [waitView setTitleText:@"解压失败"];
                [waitView waitForSeconds];
            }
        }];
    }
}


- (void)readFiles:(NSString *)path fileName:(NSString *)fileName
{
    NSMutableArray *list = [NSMutableArray arrayWithCapacity:0];
    NSFileManager *fm = [NSFileManager defaultManager];
    NSArray *subFilePath = [fm contentsOfDirectoryAtPath:path error:nil];
    for (NSString * fileName in subFilePath)
    {
        if (![fileName isEqualToString:@".DS_Store"])
        {
            NSMutableDictionary *e = [[NSMutableDictionary alloc] initWithCapacity:0];
            [e setObject:path forKey:@"path"];
            [e setObject:fileName forKey:@"fileName"];
            BOOL isDir = NO;
            [fm fileExistsAtPath:[path stringByAppendingPathComponent:fileName] isDirectory: &isDir];
            [e setObject:boolToStr(isDir) forKey:@"isDir"];
            [e setObject:[fileName pathExtension] forKey:@"ext"];
            [list addObject:e];
        }
    }
    
    WeakSelf(self);
    dispatch_sync_on_main_queue(^{
        NSBreadData *d = [[NSBreadData alloc] init];
        [d setTitle:fileName];
        [self.breview addBreadViewTitle:d withConfigBlock:^UIView * _Nullable(NSInteger index, BOOL * _Nonnull useAnimation)
        {
            UINextTreeView *b = [[UINextTreeView alloc] init];
            [b setDataSource:list checkActionBlock:^(NSDictionary *e) {
                NSString *p = [e stringForKey:@"path"];
                NSString *n = [e stringForKey:@"fileName"];
                if ([e boolForKey:@"isDir"])
                {
                    p = [p stringByAppendingPathComponent:n];
                    [weakSelf readFiles:p fileName:n];
                }
                else
                {
                    if (weakSelf.delegateBlock)
                    {
                        weakSelf.delegateBlock(e);
                    }
                }
            }];
            return b;
        }];
    });
}
@end

二、面包屑实现(控制器内部实现切换子页面视图)

头文件源码:

objectivec 复制代码
//
//  UIBreadView.h
//
//  Copyright © 2021 dtx. All rights reserved.
//

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface NSBreadData : NSObject
@property (nonatomic,strong) NSString *title;
@end

typedef NS_ENUM(NSInteger,UIBreadViewType){
    UIBreadViewBreadType=0, //面包屑模式,默认
    UIBreadViewSearchType,  //搜索模式
    UIBreadViewHyborType,   //混合模式(面包屑搜索均显示)
};

@interface UIBreadView : UIView


//仅有一个面包屑及动画切换的容器
+ (UIBreadView *)breadViewWithFrame:(CGRect)frame viewType:(UIBreadViewType)viewType;

//有一个面包屑及动画切换的容器及可添加的不进行动画切换的容器
+ (UIBreadView *)breadViewWithFrame:(CGRect)frame viewType:(UIBreadViewType)viewType positionFixView:(UIView * (^)(void))positionFixView;

- (void)addBreadViewTitle:(NSBreadData *)data withConfigBlock:(UIView* _Nullable (^)(NSInteger index,BOOL *useAnimation)) setupBlock;

//block返回YES,则隐藏面包屑
- (void)registerSelectActionBlock:(BOOL (^)(NSInteger index))actionBlock;

- (void)registerSearchKeywordBlock:(void (^)(NSString *keyword,BOOL willResign))aBlock;

//搜索UI自定义
- (void)registerConfigurationSearchInterfaceBlock:(void (^)(UIView *pview))aBlock;

- (BOOL)canPopToOneView;
- (CGFloat)breadNavigatorHeight;
- (CGFloat)breadNavigatory;

- (void)setHiddenNavigatorBreadHidden:(BOOL)flag;

- (UIView *)parentView:(UIView *)selfView;
- (UIView *)currentView;


- (void)resignSearchFieldResponder;

- (void)setReturnKeyType:(UIReturnKeyType)type;
//面包屑清除数据回归初始状态
- (void)breadcrumbClearingData;
@end

NS_ASSUME_NONNULL_END

实现文件:

objectivec 复制代码
//
//  UIBreadView.m
//  Copyright © 2021 dtx. All rights reserved.
//

#import "UIBreadView.h"
#import "NSExtentionSloter.h"
#import "SearchBarDisplayCenter.h"
#import "imHeaders.h"

typedef BOOL (^UIBreadViewActionBlock)(NSInteger index);

typedef void (^UIBreadViewSearchKeywordBlock)(NSString *keyword,BOOL willResign);

@interface NSBreadData ()
@property (nonatomic,assign) BOOL isSelected;

@property (nonatomic,assign) CGFloat itemWidth;

//如果有sourceView,则内部处理点击事件切换页面,如果无,将事件反馈到控制器处理
@property (nonatomic,weak) UIView *sourceView;
@end

@implementation NSBreadData
@synthesize title,sourceView,itemWidth,isSelected;
@end


@interface UIBreadView ()<UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout,SearchBarDisplayCenterDelegate>
{
    UICollectionView *textView;
    UIView *contentView;
    
    NSInteger lastHiglightedRow;
    NSMutableArray *dataList;
}

@property (nonatomic,copy) UIBreadViewActionBlock actionBlock;

@property (nonatomic,copy) UIBreadViewSearchKeywordBlock searchBlock;

//是否显示搜索组件进行搜索,如果显示了搜索则不再显示面包屑
@property (nonatomic,assign) UIBreadViewType viewWorkType;

@property (nonatomic,strong) UIView *fixedContainerView;

@property (nonatomic, strong) UIImageView *sepView;
@end

@implementation UIBreadView
@synthesize actionBlock,viewWorkType;

+ (UIBreadView *)breadViewWithFrame:(CGRect)frame viewType:(UIBreadViewType)viewType
{
    UIBreadView *view = [[UIBreadView alloc] initWithFrame:frame];
    [view setViewWorkType:viewType];
    [view setupUI];
    return view;
}


+ (UIBreadView *)breadViewWithFrame:(CGRect)frame viewType:(UIBreadViewType)viewType positionFixView:(UIView * (^)(void))positionFixView
{
    UIBreadView *view = [[UIBreadView alloc] initWithFrame:frame];
    [view setViewWorkType:viewType];
    if (positionFixView)
    {
        UIView *fview = positionFixView();
        [view setFixedContainerView:fview];
    }
    [view setupUI];
    return view;
}


- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame])
    {
        self->lastHiglightedRow = -1;
        self.viewWorkType = UIBreadViewBreadType;
    }
    return self;
}


- (void)setFrame:(CGRect)frame
{
    [super setFrame:frame];
    CGRect rt = contentView.frame;
    rt.size.height = frame.size.height-rt.origin.y;
    [contentView setFrame:rt];
    
    for (UIView *aview in contentView.subviews)
    {
        [aview setFrame:CGRectMake(0, 0, frame.size.width, rt.size.height)];
    }
}

- (void)setupUI{
    dataList = [[NSMutableArray alloc] initWithCapacity:0];
    
    CGRect rt = CGRectMake(20, 0, self.bounds.size.width-40, 44);
    UICollectionViewFlowLayout *flowLayout=[[UICollectionViewFlowLayout alloc] init];
    [flowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
    
    textView = [[UICollectionView alloc] initWithFrame:rt collectionViewLayout:flowLayout];
//    textView.backgroundColor = [UIColor yellowColor];
    [textView setDelegate:self];
    [textView setDataSource:self];
//    [textView setPagingEnabled:YES];
    [textView setBackgroundColor:[UIColor clearColor]];
    [textView setShowsHorizontalScrollIndicator:NO];
    [textView setShowsVerticalScrollIndicator:NO];
    [textView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"dequeueIdentifier"];
    [self addSubview:textView];
    
    CGFloat y = rt.origin.y+rt.size.height;
    if (self.viewWorkType == UIBreadViewSearchType)
    {
        [textView setHidden:YES];
        CGRect rt = CGRectMake(0, 0, ScreenWidth, 50);
        UIView *header = [[UIView alloc]initWithFrame:rt];
        header.backgroundColor = [UIColor whiteColor];

        [header setTag:404];
        [self addSubview:header];
        
        SearchBarDisplayCenter *searchBar = [[SearchBarDisplayCenter alloc]initWithFrame:CGRectMake(0, 3, ScreenWidth, 47)];
        searchBar.userInteractionEnabled = YES;
        searchBar.placeholderStr = @"搜索";
        [searchBar breadChangeFrameAndSearchIcon];

//        searchBar.seachIconIV.image = [UIImage imageInImBundle:@"bread_search"];
//        
//        [searchBar.seachIconIV mas_updateConstraints:^(MASConstraintMaker *make) {
//          
//            make.width.mas_equalTo(17);
//            make.height.mas_equalTo(17);
//        }];
//
//        searchBar.placeholderColor = colorFromText(@"#999999");
        [searchBar setTag:405];
        searchBar.backgroundColor = [UIColor whiteColor];
        [searchBar setDelegate:self];
        [header addSubview:searchBar];
        
        y = rt.origin.y+rt.size.height;
    }
    else if (self.viewWorkType == UIBreadViewHyborType)
    {
        rt = CGRectMake(0, 0, ScreenWidth, 50);
        UIView *header = [[UIView alloc]initWithFrame:rt];
        header.backgroundColor = [UIColor whiteColor];

        [header setTag:404];
        [self addSubview:header];
        
        SearchBarDisplayCenter *searchBar = [[SearchBarDisplayCenter alloc]initWithFrame:CGRectMake(0, 3, ScreenWidth, 47)];
        [searchBar setTag:405];
        searchBar.userInteractionEnabled = YES;
        searchBar.placeholderStr = @"搜索";

        [searchBar breadChangeFrameAndSearchIcon];


        [searchBar setDelegate:self];
        [header addSubview:searchBar];
        
        y = rt.origin.y+rt.size.height;
        rt = textView.frame;
        rt.origin.y = y;
        [textView setFrame:rt];
        
        y = rt.origin.y+rt.size.height;
    }
    [textView setDataObject:NSStringFromCGRect(textView.frame)];
    
    rt = CGRectMake(0, y, self.bounds.size.width, 10);
    UIImageView *sepView = [[UIImageView alloc] initWithFrame:rt];
    self.sepView = sepView;
    [sepView setBackgroundColor:DSTextPlaceColor];

    [self addSubview:sepView];
    
    y = rt.origin.y+rt.size.height;
    if (self.fixedContainerView)
    {
        rt = self.fixedContainerView.frame;
        rt.origin.y = y;
        [self.fixedContainerView setFrame:rt];
        [self addSubview:self.fixedContainerView];
        y = rt.origin.y+rt.size.height;
    }
    rt = CGRectMake(0, y, self.bounds.size.width, self.bounds.size.height- (rt.origin.y+rt.size.height));
    contentView = [[UIView alloc] initWithFrame:rt];
    [contentView setBackgroundColor:[UIColor whiteColor]];
    [contentView setTag:90001];
    [self addSubview:contentView];
}

- (void)addBreadViewTitle:(NSBreadData *)data withConfigBlock:(UIView* _Nullable (^)(NSInteger index,BOOL *useAnimation)) setupBlock
{
    WeakSelf(self);
    __weak typeof(dataList) thisDataList = dataList;
    __weak typeof(textView) thisTextView = textView;
    __weak typeof(contentView) thisContentView = contentView;
    
    [textView performBatchUpdates:^{
        CGFloat w = [data.title stringSizeWithFont:[UIFont systemFontOfSize:14]].width;
        if (thisDataList.count > 0)
        {
            w += 28;
        }
        data.itemWidth = w;
        [data setIsSelected:NO];

        [thisDataList addObject:data];
        [thisTextView insertItemsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:thisDataList.count-1 inSection:0]]];

        if (thisDataList.count > 1)
        {
            NSBreadData *e = [thisDataList objectAtIndex:thisDataList.count-2];
            [e setIsSelected:YES];

            self->lastHiglightedRow = thisDataList.count-3;
            if (self->lastHiglightedRow > -1)
            {
//                e = [dataList objectAtIndex:lastHiglightedRow];
//                [e setIsSelected:NO];
//
//                [textView reloadItemsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:lastHiglightedRow inSection:0]]];
            }

            [thisTextView reloadItemsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:thisDataList.count-2 inSection:0]]];
        }
    } completion:^(BOOL finished) {

    }];
    if (setupBlock)
    {
        NSInteger count = contentView.subviews.count;
//        for (NSInteger idx=0;idx<contentView.subviews.count;idx++)
//        {
//            UIView *view = [contentView.subviews objectAtIndex:idx];
//            CGRect rt = view.frame;
//            rt.origin.x = - (count-idx)*self.bounds.size.width;
//            [view setFrame:rt];
//        }
        BOOL useAnimation = YES;
        UIView *view = setupBlock(count,&useAnimation);
        __weak typeof(view) thisView = view;
        data.sourceView = view;
        if (view)
        {
            CGRect rt = view.frame;
            rt.origin.x = thisContentView.subviews.count>0?weakSelf.bounds.size.width:0;
            rt.size = thisContentView.frame.size;
            [view setFrame:rt];
            [thisContentView addSubview:thisView];

            if (thisContentView.subviews.count>0)
            {
                if (useAnimation)
                {
                    [UIView animateWithDuration:0.3 animations:^
                    {
                        CGRect rt = thisView.frame;
                        rt.origin.x = 0;
                        [thisView setFrame:rt];
                    }
                    completion:^(BOOL finished)
                    {

                    }];
                }
                else
                {
                    CGRect rt = thisView.frame;
                    rt.origin.x = 0;
                    [thisView setFrame:rt];
                }
            }
        }
    }
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self->dataList.count-1 inSection:0];
    [self->textView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionRight animated:YES];
};


- (void)setReturnKeyType:(UIReturnKeyType)type
{
    SearchBarDisplayCenter *searchBar = [[self viewWithTag:404] viewWithTag:405];
    searchBar.searchField.returnKeyType = type;
}

- (UIView *)parentView:(UIView *)selfView
{
    NSInteger index = [contentView.subviews indexOfObject:selfView];
    if (index > 0)
    {
        return [contentView.subviews objectAtIndex:index-1];
    }
    return nil;
}


- (UIView *)currentView
{
    return [contentView.subviews lastObject];
}



- (void)registerSelectActionBlock:(BOOL (^)(NSInteger index))actionBlock
{
    [self setActionBlock:actionBlock];
}


- (void)registerSearchKeywordBlock:(void (^)(NSString *keyword,BOOL willResign))aBlock
{
    [self setSearchBlock:aBlock];
}

- (void)registerConfigurationSearchInterfaceBlock:(void (^)(UIView *pview))aBlock
{
    SearchBarDisplayCenter *searchBar = [[self viewWithTag:404] viewWithTag:405];
    CGRect ft = searchBar.frame;
    UIView *aview = [[UIView alloc] initWithFrame:ft];
    [aview setUserInteractionEnabled:YES];
    [[self viewWithTag:404] addSubview:aview];
    
    aBlock(aview);
}

- (CGSize)itemSizeWithIndex:(NSIndexPath *)indexPath{
    NSBreadData *data = [dataList objectAtIndex:indexPath.row];
    CGFloat w = data.itemWidth;
    return CGSizeMake(w+5, textView.frame.size.height);
}


- (void)setHiddenNavigatorBreadHidden:(BOOL)flag
{
    if (textView.isHidden != flag)
    {
        [textView setHidden:flag];
        if (flag)
        {
            [UIView animateWithDuration:0.3 animations:^
            {
                CGRect rt = self->textView.frame;
                rt.origin.y = -rt.size.height;
                [self->textView setFrame:rt];
                
                CGFloat y = 0;
                if ([self viewWithTag:404])
                {
                    y = [self viewWithTag:404].frame.origin.y+[self viewWithTag:404].frame.size.height;
                }
                
                rt = CGRectMake(0, y, self.bounds.size.width, 5);
                
                [self.sepView setFrame:rt];
                
                y += 5;
                
                rt = CGRectMake(0, y, self.bounds.size.width, self.bounds.size.height-y);
                [self->contentView setFrame:rt];
            }
            completion:^(BOOL finished)
            {
                CGRect rt = self->textView.frame;
                rt.origin.x = self.bounds.size.width;
                rt.origin.y = 0;
                [self->textView setFrame:rt];
            }];
        }
        else
        {
            [UIView animateWithDuration:0.3 animations:^
            {
                CGRect rt = self->textView.frame;
                rt.origin.x = 20;
                rt.origin.y = CGRectFromString((NSString *)[self->textView dataObject]).origin.y;
                [self->textView setFrame:rt];
                
                CGFloat y = rt.origin.y+rt.size.height;
                
                rt = CGRectMake(0, y, self.bounds.size.width, 5);
                
                [self.sepView setFrame:rt];
                
                y += 5;
                
                rt = CGRectMake(0, y, self.bounds.size.width, self.bounds.size.height-y);
                [self->contentView setFrame:rt];
            }
            completion:^(BOOL finished)
            {
                
            }];
        }
    }
    for (UIView *aview in contentView.subviews)
    {
        [aview setFrame:CGRectMake(0, 0, contentView.size.width, contentView.size.height)];
    }
}


- (BOOL)canPopToOneView
{
    BOOL flag = NO;
    if (dataList.count==0) {
        return flag;
    }
    NSBreadData *mObject = [dataList lastObject];
    if (mObject.sourceView && dataList.count>1)
    {
        flag = YES;
        [self poptoOneViewWithAnimation:dataList.count-2];
    }
    
    return flag;
}


- (CGFloat)breadNavigatorHeight
{
    if (self.viewWorkType == UIBreadViewSearchType)
    {
        return MAX(textView.frame.size.height, [self viewWithTag:404].frame.size.height);
    }
    else if (self.viewWorkType == UIBreadViewHyborType)
    {
        return textView.frame.size.height+[self viewWithTag:404].frame.size.height;
    }
    else
    {
        return textView.frame.size.height;
    }
}


- (CGFloat)breadNavigatory
{
    return [self viewWithTag:404].frame.origin.y+[self viewWithTag:404].frame.size.height;
}


- (void)resignSearchFieldResponder
{
    SearchBarDisplayCenter *searchBar = [[self viewWithTag:404] viewWithTag:405];
    [searchBar restoreInitialState];
    [searchBar.searchField resignFirstResponder];
    [self poptoOneViewWithAnimation:1];
}


- (void)poptoOneViewWithAnimation:(NSInteger)row
{
    if (self.actionBlock)
    {
        BOOL flag =  self.actionBlock(row);
        [self setHiddenNavigatorBreadHidden:flag];
    }
    
    NSBreadData *mObject = [dataList objectAtIndex:row];
    if (mObject.sourceView)
    {
        for (NSInteger ix=dataList.count-1; ix>row;ix--)
        {
            NSBreadData *mObject = [dataList objectAtIndex:ix];
            UIView *aview = mObject.sourceView;
            [UIView animateWithDuration:0.3 animations:^
            {
                CGRect rt = aview.frame;
                rt.origin.x = self.bounds.size.width;
                [aview setFrame:rt];
            }
            completion:^(BOOL finished)
            {
                [aview removeFromSuperview];
            }];
        }
        [dataList removeObjectsInRange:NSMakeRange(row+1, dataList.count- (row+1))];
        NSBreadData *m = [dataList lastObject];
        [m setIsSelected:NO];
        
        if (dataList.count > 1)
        {
            m = [dataList objectAtIndex:dataList.count-2];
            [m setIsSelected:YES];
        }
        
        if (textView)
        {
            [textView reloadSections:[NSIndexSet indexSetWithIndex:0]];
        }
    }
   
}


- (void)breadcrumbClearingData {
    if (self.actionBlock)
    {
        BOOL flag =  self.actionBlock(0);
        [self setHiddenNavigatorBreadHidden:flag];
    }
    if (dataList.count > 0) {
//        for (NSInteger ix=0; ix>dataList.count;ix++)
//        {
//            NSBreadData *mObject = [dataList objectAtIndex:ix];
//            UIView *aview = mObject.sourceView;
//                [aview removeFromSuperview];
//        }
        [dataList removeAllObjects];
    }
    if (textView)
    {
        [textView reloadSections:[NSIndexSet indexSetWithIndex:0]];
    }
}
#pragma mark - SearchBarDisplayCenterDelegate
- (void)getSearchKeyWordWhenChanged:(NSString *)searchWord
{
    if (self.searchBlock)
    {
        self.searchBlock(searchWord,NO);
    }
}


- (void)textFieldBecomeResponder:(NSString*)text
{
    if (self.searchBlock)
    {
        self.searchBlock(text,NO);
    }
}

- (void)textFieldResignResponder:(NSString*)text
{
    if (self.searchBlock)
    {
        self.searchBlock(text,YES);
    }
}

#pragma mark - UICollectionView
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return 1;
}


- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    NSInteger count = dataList.count;
    return count;
}



- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
    return 0;
}


- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
    return 0;
}



- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return [self itemSizeWithIndex:indexPath];
}



// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"dequeueIdentifier" forIndexPath:indexPath];
    [cell.contentView setBackgroundColor:[UIColor clearColor]];

    CGSize size = [self itemSizeWithIndex:indexPath];
    NSBreadData *mObject = [dataList objectAtIndex:indexPath.row];
    CGFloat x = 5;
    if (indexPath.row>0)
    {
        CGRect rt = CGRectMake(x, (size.height-10)/2, 10, 10);
        UIImageView *iconView = [cell.contentView viewWithTag:90];
        if (!iconView)
        {
            iconView = [[UIImageView alloc] initWithFrame:rt];
            [iconView setImage:IMAGE_INIM_NAME(@"bookList_xiayiye")];
            [iconView setTag:90];
            [cell.contentView addSubview:iconView];
        }
        if (mObject.isSelected)
        {
            [iconView setTintColor:RGB(0, 125, 255)];
        }
        
        x += rt.size.width;
    }
    
    [[cell.contentView viewWithTag:90] setHidden:indexPath.row == 0];
    
    CGRect rt = CGRectMake(x, 0, size.width-x, size.height);
    UIButton *button = [cell.contentView viewWithTag:91];
    if (!button)
    {
        button = [UIButton buttonWithType:UIButtonTypeCustom];
        [button setTag:91];
        [button.titleLabel setFont:[UIFont systemFontOfSize:14]];
        [button setTitleColor:RGB(40, 40, 40) forState:UIControlStateNormal];
        [button setTitleColor:RGB(0, 125, 255) forState:UIControlStateSelected];
        [cell.contentView addSubview:button];
    }
    [button setUserInteractionEnabled:NO];
    [button setFrame:rt];
    [button setTitle:mObject.title forState:UIControlStateNormal];
    [button setDataObject:mObject];
    [button setSelected:mObject.isSelected];
    
    [cell setBackgroundColor:[UIColor clearColor]];
    
    return cell;
}


- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
//    UICollectionViewCell *cell = [contentView cellForItemAtIndexPath:indexPath];
    [self poptoOneViewWithAnimation:indexPath.row];
}
@end

完毕,相关的资源文件自己寻找整理,这里就不贴了,相关的一些个人开发依赖,有兴趣的同学可以留言找我要!

三、使用

objectivec 复制代码
ZipRarViewController *c = [[ZipRarViewController alloc] init];
//传入压缩包路径,支持本地文件及远程文件URL
[c setFilePath:url];
//文中路径进行MD5,目的是区分记录解压记录,已解压过的后期不再解压而是直接读取展示
[c setFileFlag:[fileFlag md5Byte32Lower]];
[c setDelegateBlock:^(NSDictionary *data) {
    NSString *p = [data stringForKey:@"path"];
    NSString *f = [data stringForKey:@"fileName"];
    weakSelf.fileURL = [NSURL fileURLWithPath:[p                 
       stringByAppendingPathComponent:f]];
    [weakSelf openDocument:weakSelf.fileURL];
}];
[self.navigationController pushViewController:c animated:YES];


//打开文件方法
- (void)openDocument:(NSURL *)url {
    if ([QLPreviewController canPreviewItem:url]) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [weakSelf initKkpreview];
            });
        }
}


- (void)initKkpreview {
    self.kkpreview = [[QLPreviewController alloc] init];
    self.kkpreview.delegate = self;
    self.kkpreview.dataSource = self;
    WeakSelf(self);
    UIView *rview = [UINaviButton naviButtonWithActionBlock:^{
        [weakSelf.kkpreview.navigationController popViewControllerAnimated:YES];
    }];
    UIBarButtonItem *item = [[UIBarButtonItem alloc]initWithCustomView:rview];
    self.kkpreview.navigationItem.leftBarButtonItem = item;
    [self.navigationController pushViewController:self.kkpreview animated:YES];
}


#pragma mark - QLPreviewControllerDataSource
- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller{
    return 1;
}

- (id<QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index{
    return  self.fileURL;
}
相关推荐
1telescope9 小时前
MacBook 安装 nvm 管理 Node.js 多版本教程
macos·node.js
1telescope9 小时前
MacBook 安装 Oh My Zsh 完整教程
macos·mac
蜜汁小强9 小时前
macOS 上的git代理配置在哪里
git·macos·代理模式·proxy模式
蜜汁小强11 小时前
macOS 上升级到 python 3.12
开发语言·python·macos
上天_去_做颗惺星 EVE_BLUE11 小时前
Android设备与Mac/Docker全连接指南:有线到无线的完整方案
android·linux·macos·adb·docker·容器·安卓
2501_9160088911 小时前
iOS开发APP上架全流程解析:从开发到App Store的完整指南
android·ios·小程序·https·uni-app·iphone·webview
goodmao11 小时前
【macOS】【磁盘空间整理】查看大文件夹
macos
七夜zippoe12 小时前
Cython终极性能优化指南:从Python到C++的混合编程实战
c++·python·macos·cython·类型系统·内存视图
2501_915909061 天前
Charles 抓不到包怎么办?iOS 调试过程中如何判断请求路径
android·ios·小程序·https·uni-app·iphone·webview
2501_916007471 天前
iOS和iPadOS文件管理系统全面解析与使用指南
android·ios·小程序·https·uni-app·iphone·webview