当前位置: 首页 > news >正文

OC IOS 文件解压缩预览

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

来吧,come on。。。

 引用第三方库:

pod 'SSZipArchive'

开发实现:

一、控制器实现

头文件控制器定义:

//
//  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;@endNS_ASSUME_NONNULL_END

实现文件定义:

//
//  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;
@endNS_ASSUME_NONNULL_ENDtypedef 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

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

头文件源码:

//
//  UIBreadView.h
//
//  Copyright © 2021 dtx. All rights reserved.
//#import <UIKit/UIKit.h>NS_ASSUME_NONNULL_BEGIN@interface NSBreadData : NSObject
@property (nonatomic,strong) NSString *title;
@endtypedef 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;
@endNS_ASSUME_NONNULL_END

实现文件:

//
//  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

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

三、使用

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;
}

 

相关文章:

OC IOS 文件解压缩预览

热很。。热很。。。。夏天的城市只有热浪没有情怀。。。 来吧&#xff0c;come on。。。 引用第三方库&#xff1a; pod SSZipArchive 开发实现&#xff1a; 一、控制器实现 头文件控制器定义&#xff1a; // // ZipRarViewController.h // // Created by carbonzhao on 2…...

python-web应用程序-Django-From组件

python-web应用程序-Django-From组件 添加用户时 原始方法&#xff08;本质&#xff09;【麻烦】 def user_add(req):if req.method GET:return render(req,XXX.html)#POST请求处理:XXXXX-用户数据没有校验 -出现错误提示 -页面上的每一个字段都需要我们重新写一遍 -关联数…...

K8s(Kubernetes)常用命令

大家好&#xff0c;当谈及容器编排工具时&#xff0c;Kubernetes&#xff08;常简称为K8s&#xff09;无疑是当今最受欢迎和广泛使用的解决方案之一。作为一个开源的容器编排平台&#xff0c;Kubernetes 提供了丰富的功能&#xff0c;可以帮助开发人员和运维团队管理、部署和扩…...

C#-for循环语句

for循环语句 语法: for(初始化变量; 判断条件; 增量表达式) { // 内部代码 } 第一个空(初始表达式): 一般用来声明一个临时的局部变量 用来计数第二个空(条件表达式): 表明进入循环的条件 一个bool类型的值(bool类型 条件表达式 逻辑运算符)第三个空(增量表达式): 使用第一个空…...

css动画案例练习之会展开的魔方和交错的小块

这里写目录标题 一级目录二级目录三级目录 下面开始案例的练习&#xff0c;建议第一个动手操作好了再进行下一个一、交错的小块效果展示1.大致思路1.基本结构2.实现动态移动 2.最终版代码 二、会展开的魔方1.大致思路1.基本结构;2.静态魔方的构建3.让静态的魔方动起来 2.最终版…...

前端逆向之下载canvas引用的图片

前端逆向之下载canvas引用的图片 一、来源二、解决三、如果在Network这里也找不到呢&#xff1f; 一、来源 当我们用dom检查器的时候无法选中想要扒下来的图片&#xff0c;只能选中canvas&#xff0c;这种时候该怎么办呢&#xff1f; 二、解决 这个时候应该换个脑子&#xf…...

深度学习手撕代码题

目录: PyTorch实现注意力机制、多头注意力与自注意力Numpy广播机制实现矩阵间L2距离的计算Conv2D卷积的Python和C++实现Numpy实现bbox_iou的计算Numpy实现FocallossPython实现nms、softnmsPython实现BN批量归一化PyTorch卷积与BatchNorm的融合分割网络损失函数Dice Loss代码实…...

vue3 + ts 动态添加路由,刷新页面白屏问题解决方案

1、store 中添加路由的方法 2、main.ts中使用该方法 然后就可以任意刷新页面了&#xff0c;有问题可以随时滴我...........

【Kubernetes】k8s的调度约束(亲和与反亲和)

一、调度约束 list-watch 组件 Kubernetes 是通过 List-Watch 的机制进行每个组件的协作&#xff0c;保持数据同步的&#xff0c;每个组件之间的设计实现了解耦。 用户是通过 kubectl 根据配置文件&#xff0c;向 APIServer 发送命令&#xff0c;在 Node 节点上面建立 Pod 和…...

Java数据结构- Map和Set

目录 1. Map和Set2. Map的使用3. Set的使用 1. Map和Set Java中&#xff0c;Map和Set是两个接口&#xff0c;TreeSet、HashSet这两个类实现了Set接口&#xff0c;TreeMap、HashMap这两个类实现了Map接口。 带Tree的这两个类&#xff08;TreeSet、TreeMap&#xff09;底层的数…...

JVM参数配置

JVM参数的三种表示方法 在jvm中&#xff0c;jvm虚拟机参数有以下三种表示方法&#xff1a; 标准参数&#xff08;-&#xff09;所有的JVM实现都必须实现这些参数的功能&#xff0c;而且向后兼容非标准参数&#xff08;-X&#xff09;&#xff0c;默认jvm实现这些参数的功能&…...

Vue 实现的精彩动画效果

在 Vue 开发中&#xff0c;我们可以利用<transition>组件来打造各种令人惊艳的动画效果。下面来详细看看这些有趣的动画效果及其实现代码。 一、缩放类效果 zoom-in&#xff08;整体放大进入&#xff09; <template><div><button click"isShow ! …...

JVM类加载机制详解(JDK源码级别)

提示&#xff1a;从JDK源码级别彻底剖析JVM类加载机制、双亲委派机制、全盘负责委托机制、打破双亲委派机制的程序、Tomcat打破双亲委派机制、tomcat自定义类加载器详解、tomcat的几个主要类加载器、手写tomcat类加载器 文章目录 前言一、loadClass的类加载大概有如下步骤二、j…...

美国年轻人热衷床上“摆烂”,沃尔玛发掘床上用品新商机!

美国年轻人近年来热衷于床上“摆烂”生活方式&#xff0c;这反映了他们对舒适放松的追求和现代生活的压力。沃尔玛作为零售业巨头&#xff0c;敏锐地捕捉到这一市场变化&#xff0c;发现了床上用品的新商机。 美国年轻人忙碌中渴望宁静空间。床成为他们放松、逃离现实压力的理想…...

3168. 候诊室中的最少椅子数

给你一个字符串 s&#xff0c;模拟每秒钟的事件 i&#xff1a; 如果 s[i] E&#xff0c;表示有一位顾客进入候诊室并占用一把椅子。如果 s[i] L&#xff0c;表示有一位顾客离开候诊室&#xff0c;从而释放一把椅子。 返回保证每位进入候诊室的顾客都能有椅子坐的 最少 椅子…...

C# PaddleOCR 单字识别效果

C# PaddleOCR 单字识别效果 效果 说明 根据《百度办公文档识别C离线SDKV1.2用户接入文档.pdf》&#xff0c;使用C封装DLL&#xff0c;C#调用。 背景 为使客户、第三方开发者等能够更快速、方便的接入使用百度办公文档识别 SDK、促进百度 OCR产品赋能更多客户&#xff0c;特设…...

pyopengl 立方体 正投影,透视投影

目录 顶点和线的方式 划线的方式实现: 顶点和线的方式 import numpy as np from PyQt5 import QtWidgets from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton from OpenGL.GL import * from OpenGL.GLU import * import sys…...

人工智能任务5-高级算法工程师需要学习哪些课程与掌握哪些能力

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能的任务5-高级算法工程师需要学习哪些课程&#xff0c;需要掌握哪些能力。高级算法工程师需要掌握的算法模型有&#xff1a;人脸检测模型MTCNN&#xff0c;人脸识别方法Siamese network、center loss、softm…...

服务器上创建搭建gitlab

一、下载与安装 在主目录操作~ 1.使用wget下载 wget --no-check-certificate https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-14.0.1-ce.0.el7.x86_64.rpm 可以在开源软件镜像站选择合适的版本&#xff0c;版本不同页面菜单会稍有差异&#xff0c;此次选…...

LangChain学习之prompt格式化与解析器使用

1. 学习背景 在LangChain for LLM应用程序开发中课程中&#xff0c;学习了LangChain框架扩展应用程序开发中语言模型的用例和功能的基本技能&#xff0c;遂做整理为后面的应用做准备。视频地址&#xff1a;基于LangChain的大语言模型应用开发构建和评估高 2. 先准备尝试调用O…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

条件运算符

C中的三目运算符&#xff08;也称条件运算符&#xff0c;英文&#xff1a;ternary operator&#xff09;是一种简洁的条件选择语句&#xff0c;语法如下&#xff1a; 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true&#xff0c;则整个表达式的结果为“表达式1”…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...

LLMs 系列实操科普(1)

写在前面&#xff1a; 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容&#xff0c;原视频时长 ~130 分钟&#xff0c;以实操演示主流的一些 LLMs 的使用&#xff0c;由于涉及到实操&#xff0c;实际上并不适合以文字整理&#xff0c;但还是决定尽量整理一份笔…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...