1 UISearchController使用
可用于上传文件的文件列表显示页
UploadFileViewController.h
@interface UploadFileViewController : UIViewController
@end
UploadFileViewController.m
核心代码
@interface UploadFileViewController () <UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate, SearchResultViewControllerDelegate, UIDocumentInteractionControllerDelegate/*, UISearchControllerDelegate, UISearchResultsUpdating, UITextFieldDelegate*/>
@property (nonatomic, strong) UIView *navigatorView;
@property (nonatomic, strong) UIButton *backButton;
@property (nonatomic, strong) UIButton *confirmButton;
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UIImageView *titleImageView;
@property (nonatomic, strong) UploadFileTypeView *typeView;
//@property (nonatomic, strong) NSDictionary *file;
//@property (nonatomic, strong) NSArray<NSDictionary *> *fileArr;//暂时只支持一个文件
@property (nonatomic, strong) UploadFileInfo *file;
@property (nonatomic, strong) NSArray<UploadFileInfo *> *fileArr;//暂时只支持一个文件
@property (nonatomic, strong) UISearchController *searchController;
@property (nonatomic, strong) UITableView *tableview;
@property (nonatomic, strong) SearchResultViewController *resultController;
//@property (nonatomic, strong) NSArray<UploadFileInfo *> *resultArr;
@end
@implementation UploadFileViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self setupData];
[self setupView];
}
- (void)setupView
{
self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.navigatorView];
[self.view addSubview:self.backButton];
[self.view addSubview:self.confirmButton];
[self.view addSubview:self.titleLabel];
[self.view addSubview:self.titleImageView];
[self.view addSubview:self.tableview];
CGRect rectNavi = self.navigatorView.frame;
double bottom = rectNavi.origin.y + rectNavi.size.height + 8;
CGRect rectView = self.tableview.frame;
CGFloat x = rectView.origin.x;
CGFloat y = bottom;
CGFloat width = rectView.size.width;
CGFloat height = rectView.size.height - y;
self.tableview.frame = CGRectMake(x, y, width, height);
CGPoint center = self.navigatorView.center;
self.backButton.center = CGPointMake(self.backButton.center.x, center.y);
self.confirmButton.center = CGPointMake(self.confirmButton.center.x, center.y);
self.titleLabel.center = CGPointMake(center.x - self.titleImageView.frame.size.width / 2 - 2, center.y);
self.titleImageView.center = CGPointMake(center.x + self.titleLabel.frame.size.width / 2 + 2, center.y);
self.resultController = [[SearchResultViewController alloc] init];
self.resultController.fileArr = self.fileArr;
self.resultController.delegate = self;
self.searchController = [[UISearchController alloc] initWithSearchResultsController:self.resultController];
self.searchController.searchResultsUpdater = self.resultController;
self.searchController.delegate = self.resultController;
self.searchController.hidesNavigationBarDuringPresentation = YES;
self.definesPresentationContext = YES;
self.searchController.definesPresentationContext = YES;
self.searchController.searchBar.delegate = self;
self.resultController.mainController = self;
//处理添加UISearchController后UITableView的ContentSize变大的问题
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.searchController.searchBar.bounds.size.width, self.searchController.searchBar.bounds.size.height)];
[headerView addSubview:self.searchController.searchBar];
self.tableview.tableHeaderView = headerView;
}
//点击进入文件详情页
- (void)invokeDetailByData:(id)data
{
NSLog(@"app: invokeDetailByData:%@", data);
UploadFileInfo *info = (UploadFileInfo *)data;
UIDocumentInteractionController *docVC = [[UIDocumentInteractionController alloc] init];
docVC.URL = [NSURL fileURLWithPath:info.path];
docVC.delegate = self;
[docVC presentPreviewAnimated:YES];
}
//文件预览页回调
#pragma mark - UIDocumentInteractionControllerDelegate
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller
{
return self;
}
- (UIView *)documentInteractionControllerViewForPreview:(UIDocumentInteractionController *)controller
{
return self.view;
}
- (CGRect)documentInteractionControllerRectForPreview:(UIDocumentInteractionController *)controller
{
return CGRectMake(0, 30, self.view.bounds.size.width, self.view.bounds.size.height);
}
- (void)documentInteractionControllerWillBeginPreview:(UIDocumentInteractionController *)controller
{
NSLog(@"app: docVC will begin");
}
- (void)documentInteractionControllerDidEndPreview:(UIDocumentInteractionController *)controller
{
NSLog(@"app: docVC did end");
}
#pragma mark - UITableViewDelegate, UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.fileArr.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UploadFileTableViewCell *cell = (UploadFileTableViewCell *)[tableView dequeueReusableCellWithIdentifier:[UploadFileTableViewCell cellWithReuseIdentifier] forIndexPath:indexPath];
UploadFileInfo *info = self.fileArr[indexPath.row];
[cell updateCellWithData:info];
[cell updateSelectStatus:info.selected];
if (info.selected) {
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}
__weak typeof(self) weakSelf = self;
cell.detailBlock = ^(id _Nonnull data) {
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf invokeDetailByData:data];
};
// NSLog(@"app: cell indexPath.row:%ld, cell:%@, info.selected:%@", (long)indexPath.row, cell, @(info.selected));
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// [tableView deselectRowAtIndexPath:indexPath animated:YES];
UploadFileTableViewCell *cell = (UploadFileTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
UploadFileInfo *info = self.fileArr[indexPath.row];
if (info.selected) {
info.selected = NO;
self.file = nil;
} else {
info.selected = YES;
self.file = info;
}
[cell updateSelectStatus:info.selected];
[self checkConfrimButtonStatus];
NSLog(@"app: select indexPath.row:%ld, cell:%@, info.selected:%@", (long)indexPath.row, cell, @(info.selected));
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath{
UploadFileTableViewCell *cell = (UploadFileTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
UploadFileInfo *info = self.fileArr[indexPath.row];
info.selected = NO;
[cell updateSelectStatus:info.selected];
NSLog(@"app: un-select indexPath.row:%ld, cell:%@, info.selected:%@", (long)indexPath.row, cell, @(info.selected));
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
NSLog(@"app: seearchBar cancel oooooo");
if (self.resultController.file) {
//取消之前的
if (self.file != self.resultController.file) {
self.file.selected = NO;
}
self.file = self.resultController.file;
self.resultController.file = nil;//清理掉
[self checkConfrimButtonStatus];
} else {
if (!self.file.selected) {
self.file = nil;
}
}
[self.tableview reloadData];
}
#pragma mark - SearchResultViewControllerDelegate
- (void)scrollViewDidScrollAction
{
[self.searchController.searchBar endEditing:YES];
}
- (void)openFileDetailByData:(id)data
{
[self invokeDetailByData:data];
}
@end
- 说明:
1)UISearchController使用时作为HeadView,需要和UItableView配合使用。
2)文件预览有多种方式,这里使用了UIDocumentInteractionController。
搜索结果页
SearchResultViewController.h
@protocol SearchResultViewControllerDelegate <NSObject>
@optional
- (void)scrollViewDidScrollAction;
- (void)openFileDetailByData:(id)data;
@end
@interface SearchResultViewController : UIViewController <UISearchControllerDelegate, UISearchResultsUpdating>
@property (nonatomic, strong) UITableView *tableview;
@property (nonatomic, strong) UIViewController *mainController;
@property (nonatomic, strong) NSArray<UploadFileInfo *> *fileArr;
@property (nonatomic, strong) UploadFileInfo *file;
@property (nonatomic, weak) id<SearchResultViewControllerDelegate> delegate;
@end
SearchResultViewController.m
核心代码
@interface SearchResultViewController () <UITableViewDelegate, UITableViewDataSource/*, UIDocumentInteractionControllerDelegate*/>
@property (nonatomic, strong) NSArray<UploadFileInfo *> *resultArr;
@end
@implementation SearchResultViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self setupData];
[self setupView];
}
- (void)setupData
{
self.resultArr = self.fileArr;
}
- (void)setupView
{
self.definesPresentationContext = YES;
[self.view addSubview:self.tableview];
}
#pragma mark - UISearchControllerDelegate
- (void)willPresentSearchController:(UISearchController *)searchController
{
NSLog(@"app: willPresentSearchController");
CGRect mainrect = self.mainController.view.frame;
[UIView animateWithDuration:0.5 animations:^{
self.mainController.view.frame = CGRectMake(0, -24, mainrect.size.width, mainrect.size.height);
}];
}
- (void)didPresentSearchController:(UISearchController *)searchController
{
NSLog(@"app: didPresentSearchController");
}
- (void)willDismissSearchController:(UISearchController *)searchController
{
CGRect mainrect = searchController.view.frame;
[UIView animateWithDuration:0.5 animations:^{
self.mainController.view.frame = CGRectMake(0, 0, mainrect.size.width, mainrect.size.height);
}];
}
- (void)didDismissSearchController:(UISearchController *)searchController
{
}
#pragma mark - UISearchResultsUpdating
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
NSString *searchString = searchController.searchBar.text;
NSLog(@"app: searchString:%@", searchString);
if (searchString.length) {
__block NSInteger index = -1;
NSMutableArray<UploadFileInfo *> *array = [NSMutableArray array];
[self.fileArr enumerateObjectsUsingBlock:^(UploadFileInfo * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj.name containsString:searchString]) {
[array addObject:obj];
if (obj.selected) {
index = array.count - 1;
}
}
}];
self.resultArr = array.copy;
[self.tableview reloadData];
}
}
#pragma mark - UITableViewDelegate, UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.resultArr.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UploadFileTableViewCell *cell = (UploadFileTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"UPloadFileResult" forIndexPath:indexPath];
UploadFileInfo *info = self.resultArr[indexPath.row];
[cell updateCellWithData:info];
__weak typeof(self) weakSelf = self;
cell.detailBlock = ^(id _Nonnull data) {
__strong typeof(weakSelf) strongSelf = weakSelf;
[strongSelf invokeDetailByData:data];
};
[cell updateSelectStatus:info.selected];
if (info.selected) {
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// [tableView deselectRowAtIndexPath:indexPath animated:YES];
UploadFileTableViewCell *cell = (UploadFileTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
UploadFileInfo *info = self.resultArr[indexPath.row];
if (info.selected) {
info.selected = NO;
self.file = nil;
} else {
info.selected = YES;
self.file = info;
}
[cell updateSelectStatus:info.selected];
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
UploadFileTableViewCell *cell = (UploadFileTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
UploadFileInfo *info = self.resultArr[indexPath.row];
info.selected = NO;
[cell updateSelectStatus:info.selected];
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (decelerate) {
if (self.delegate && [self.delegate respondsToSelector:@selector(scrollViewDidScrollAction)]) {
[self.delegate scrollViewDidScrollAction];
}
}
}
@end
Model
UploadFileInfo.h
@interface UploadFileInfo : NSObject
@property (nonatomic, strong) NSString *path;
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSDate *createDate;
@property (nonatomic, strong) NSDate *modifyDate;
@property (nonatomic, strong) NSNumber *size;
@property (nonatomic, assign) BOOL ios;
@property (nonatomic, assign) BOOL selected;
+ (UploadFileInfo *)getUploadFileInfoByDictionary:(NSDictionary *)dic;
- (NSDictionary *)convertToDictionary;
@end
UploadFileInfo.m
@implementation UploadFileInfo
+ (UploadFileInfo *)getUploadFileInfoByDictionary:(NSDictionary *)dic
{
if (!dic) {
return nil;
}
UploadFileInfo *info = [UploadFileInfo new];
info.path = dic[@"path"];
info.name = dic[@"name"];
info.size = dic[@"size"];
info.ios = YES;
info.createDate = dic[@"createDate"];
info.modifyDate = dic[@"modifyDate"];
info.selected = NO;
return info;
}
- (NSDictionary *)convertToDictionary
{
NSDate *currentDate = [NSDate date];
return @{
@"path": self.path.length ? self.path : @"",
@"name": self.name.length ? self.name : @"",
@"size": self.size ? self.size : @(0),
@"ios": @(YES),
@"modifyDate": self.modifyDate ? self.modifyDate : currentDate,
@"createDate": self.createDate ? self.createDate : currentDate
};
}
@end
补充:扩大UIView的点击范围
UploadFileDetainImageView.h
@interface UploadFileDetainImageView : UIImageView
@end
UploadFileDetainImageView.m
@implementation UploadFileDetainImageView
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
return CGRectContainsPoint(CGRectInset(self.bounds, -5, -5), point);
}
@end
2 UISearchController相关
UISearchController
- 参考:
https://www.jianshu.com/p/80959b44e378
https://blog.csdn.net/u013712343/article/details/107335085
http://www.zzvips.com/article/145111.html
https://blog.csdn.net/weixin_43144634/article/details/82457288
UISearchController没有隐藏导航栏
- 参考:
https://blog.csdn.net/ljc_563812704/article/details/103164010
https://blog.csdn.net/m0_55124878/article/details/124151352
https://www.jianshu.com/p/17b0aae458f9
ios自定义SearchController
- 参考:
https://www.jianshu.com/p/e248e73f3484
https://zhuanlan.zhihu.com/p/22718679
https://www.jianshu.com/p/c6bfadb4bfff
UISearchController显示崩溃
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modal view controller on itself. Presenting controller is <UISearchController: 0x107937a00>.'
- 处理:
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
这里需要设置nil,而不是self。
hidesNavigationBarDuringPresentation不生效
- 参考:
https://blog.csdn.net/weixin_34348174/article/details/88007298
https://blog.csdn.net/yishengzhiai005/article/details/79129366/
SearchResultsController开启新页面时searchBar向上位移
监听searchBar的clear按钮事件
_UITextFieldClearButton
参考:
https://blog.csdn.net/weixin_33904756/article/details/91465829
https://www.cnblogs.com/qingzZ/p/15405571.html
https://www.orcode.com/question/551405_k23c5e.html
https://www.cnblogs.com/Clin/p/3383779.htmlUISearchBar监听clear button
参考:
https://blog.csdn.net/dexin5195/article/details/50978409
https://blog.csdn.net/luxuewei5214/article/details/102468935?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_default&utm_relevant_index=2
uisearchcontroller适配
uisearchcontroller添加后tableview的contentsize变大
- 处理:
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, self.searchController.searchBar.height)];
[headerView addSubview:self.searchController.searchBar];
self.tableView.tableHeaderView = headerView;