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;
}
相关推荐
Java小白笔记10 小时前
Mac中安装homebrew
macos
HerayChen14 小时前
HbuildderX运行到手机或模拟器的Android App基座识别不到设备 mac
android·macos·智能手机
hairenjing112314 小时前
在 Android 手机上从SD 卡恢复数据的 6 个有效应用程序
android·人工智能·windows·macos·智能手机
DisonTangor15 小时前
苹果发布iOS 18.2首个公测版:Siri接入ChatGPT、iPhone 16拍照按钮有用了
ios·chatgpt·iphone
- 羊羊不超越 -15 小时前
App渠道来源追踪方案全面分析(iOS/Android/鸿蒙)
android·ios·harmonyos
小李飞刀李寻欢16 小时前
Mac电脑如何解压rar压缩包
macos·rar·解压
Java小白笔记16 小时前
Mac中禁用系统更新
macos
AndyFrank16 小时前
mac crontab 不能使用问题简记
linux·运维·macos
Mac新人16 小时前
一招解决Mac没有剪切板历史记录的问题
macos·mac
王拴柱16 小时前
Mac保护电池健康,延长电池使用寿命的好方法
macos·mac