文章结构
- 其他搜索类
- UISearchController中searchBar视图结构
- 不同iOS版本searchBar的使用方式
- searchBar不显示
- definesPresentationContext理解
- 处于搜索状态下禁用导航控制器滑动返回
- searchBar白条
其他搜索API
还有一个UISearchDisplayController,该类在iOS8开始弃用,但是在iOS13开始如果继续使用该类会crash,苹果强制不让用了。
UISearchController中searchBar视图结构
在iphoneX中的UI展示如下:
在iOS13前UISearchBarBackground(视图结构红色框中)这个UIImageView的frame如UI样式图中红色框,其是UISearchBar的子视图,但是其frame比UISearchBar大,拓展到状态栏,所以在iOS13前通过设置UISearchBar的barTintColor可以改变其颜色,保证UI样式中绿色框不是透明的,否则列表往上滑时候内容在绿色框处是可见的。在iOS13后其frame和searchBar一样,所以通过设置barTintColor,绿色框处还是透明的,UI看起来不协调。
不同iOS版本searchBar的使用方式
代码如下:
if (@available(iOS 11, *)){
self.navigationItem.searchController = searchVC;
}else {
self.tableView.tableHeaderView = searchVC.searchBar;
}
如UISearchController中searchBar视图结构中所述,在iOS13前把searchBar设置为tableView的header在iphoneX中显示还是正常,但是iOS13后就必须通过如下方式使用
self.navigationItem.searchController = searchVC;
否则UI样式图中的绿色框部分将是透明的。
searchBar不显示
如果通过如下方式使用searchBar
self.navigationItem.searchController = searchVC;
在刚进入控制器时候,searchBar是隐藏的,通过如下设置让其总是显示
self.navigationItem.hidesSearchBarWhenScrolling = NO;
如果需要进入控制器时searchBar不隐藏,在滑动时候searchBar隐藏,如下设置即可
- (void)viewDidLoad {
[super viewDidLoad];
//初始化
UISearchController *searchVC = ...;
if (@available(iOS 11, *)) {
self.navigationItem.searchController = searchVC;
self.navigationItem.hidesSearchBarWhenScrolling = NO;
}
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if (@available(iOS 11, *)) {
self.navigationItem.hidesSearchBarWhenScrolling = YES;
}
}
definesPresentationContext理解
Specify that this view controller determines how the search controller is presented.
The search controller should be presented modally and match the physical size of this view controller.
表明设置了该值为YES的控制器决定UISearchController该如何被presented,UISearchController应该被模态展示且尺寸和设置了该值为YES的控制器尺寸一样。
Determines which parent view controller's view should be presented over for presentations of type
UIModalPresentationCurrentContext. If no ancestor view controller has this flag set, then the presenter
will be the root view controller.
如果系统没有找到设置了该值为YES的控制器,则将使用rootVC来present UISearchController。
处于搜索状态下禁用导航控制器滑动返回
当处于搜索模式下应该禁用导航控制器滑动放回,否则当向右滑再向左滑回来时,UI不好看
- (void)willPresentSearchController:(UISearchController *)searchController
{
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
- (void)didDismissSearchController:(UISearchController *)searchController
{
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
}
searchBar白条
简单描述下,从A控制器push到B控制器,A控制器里导航栏是隐藏的,B控制器的导航栏不隐藏且通过navigationItem设置的UISearchController,当滑动返回A控制器时,有一条白色的过度动画。这个问题在stackOver中也有描述。
里面也有解决代码,在B控制器里写入如下代码解决。
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if (@available(iOS 11, *)){
if (self.navigationItem.searchController == nil) return;
UIView *containerView = self.transitionCoordinator.containerView;
CGFloat currentPosition = self.navigationItem.searchController.searchBar.superview.x;
[self.transitionCoordinator animateAlongsideTransitionInView:containerView animation:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
UIViewController * toVC = [context viewControllerForKey:UITransitionContextToViewControllerKey];
//这里的判断根据自己代码实际情况判断,也就是A控制器的判断
if ([toVC isKindOfClass:[MeViewController class]]){
CGRect frame = self.navigationItem.searchController.searchBar.superview.frame;
frame.origin.x = self.view.width;
self.navigationItem.searchController.searchBar.superview.frame = frame;
}
} completion:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
CGRect frame = self.navigationItem.searchController.searchBar.superview.frame;
frame.origin.x = currentPosition ?: 0;
self.navigationItem.searchController.searchBar.superview.frame = frame;
}];
}
}