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 文件解压缩预览
热很。。热很。。。。夏天的城市只有热浪没有情怀。。。 来吧,come on。。。 引用第三方库: pod SSZipArchive 开发实现: 一、控制器实现 头文件控制器定义: // // ZipRarViewController.h // // Created by carbonzhao on 2…...
python-web应用程序-Django-From组件
python-web应用程序-Django-From组件 添加用户时 原始方法(本质)【麻烦】 def user_add(req):if req.method GET:return render(req,XXX.html)#POST请求处理:XXXXX-用户数据没有校验 -出现错误提示 -页面上的每一个字段都需要我们重新写一遍 -关联数…...

K8s(Kubernetes)常用命令
大家好,当谈及容器编排工具时,Kubernetes(常简称为K8s)无疑是当今最受欢迎和广泛使用的解决方案之一。作为一个开源的容器编排平台,Kubernetes 提供了丰富的功能,可以帮助开发人员和运维团队管理、部署和扩…...
C#-for循环语句
for循环语句 语法: for(初始化变量; 判断条件; 增量表达式) { // 内部代码 } 第一个空(初始表达式): 一般用来声明一个临时的局部变量 用来计数第二个空(条件表达式): 表明进入循环的条件 一个bool类型的值(bool类型 条件表达式 逻辑运算符)第三个空(增量表达式): 使用第一个空…...

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

前端逆向之下载canvas引用的图片
前端逆向之下载canvas引用的图片 一、来源二、解决三、如果在Network这里也找不到呢? 一、来源 当我们用dom检查器的时候无法选中想要扒下来的图片,只能选中canvas,这种时候该怎么办呢? 二、解决 这个时候应该换个脑子…...
深度学习手撕代码题
目录: 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中使用该方法 然后就可以任意刷新页面了,有问题可以随时滴我...........

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

Java数据结构- Map和Set
目录 1. Map和Set2. Map的使用3. Set的使用 1. Map和Set Java中,Map和Set是两个接口,TreeSet、HashSet这两个类实现了Set接口,TreeMap、HashMap这两个类实现了Map接口。 带Tree的这两个类(TreeSet、TreeMap)底层的数…...

JVM参数配置
JVM参数的三种表示方法 在jvm中,jvm虚拟机参数有以下三种表示方法: 标准参数(-)所有的JVM实现都必须实现这些参数的功能,而且向后兼容非标准参数(-X),默认jvm实现这些参数的功能&…...
Vue 实现的精彩动画效果
在 Vue 开发中,我们可以利用<transition>组件来打造各种令人惊艳的动画效果。下面来详细看看这些有趣的动画效果及其实现代码。 一、缩放类效果 zoom-in(整体放大进入) <template><div><button click"isShow ! …...

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

美国年轻人热衷床上“摆烂”,沃尔玛发掘床上用品新商机!
美国年轻人近年来热衷于床上“摆烂”生活方式,这反映了他们对舒适放松的追求和现代生活的压力。沃尔玛作为零售业巨头,敏锐地捕捉到这一市场变化,发现了床上用品的新商机。 美国年轻人忙碌中渴望宁静空间。床成为他们放松、逃离现实压力的理想…...
3168. 候诊室中的最少椅子数
给你一个字符串 s,模拟每秒钟的事件 i: 如果 s[i] E,表示有一位顾客进入候诊室并占用一把椅子。如果 s[i] L,表示有一位顾客离开候诊室,从而释放一把椅子。 返回保证每位进入候诊室的顾客都能有椅子坐的 最少 椅子…...

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

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-高级算法工程师需要学习哪些课程与掌握哪些能力
大家好,我是微学AI,今天给大家介绍一下人工智能的任务5-高级算法工程师需要学习哪些课程,需要掌握哪些能力。高级算法工程师需要掌握的算法模型有:人脸检测模型MTCNN,人脸识别方法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 可以在开源软件镜像站选择合适的版本,版本不同页面菜单会稍有差异,此次选…...
LangChain学习之prompt格式化与解析器使用
1. 学习背景 在LangChain for LLM应用程序开发中课程中,学习了LangChain框架扩展应用程序开发中语言模型的用例和功能的基本技能,遂做整理为后面的应用做准备。视频地址:基于LangChain的大语言模型应用开发构建和评估高 2. 先准备尝试调用O…...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...

视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...

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…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...

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

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...

Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...