最近做搜索的时候使用了UISearchController遇到以下的问题:
先说说大概实现:可以对tableView上的数据进行搜索,并在原有的tableView上显示出搜索结果。tableViewCell是可以点击的,并且进行界面的切换。
问题一:
点击SearchBar进入了编辑状态时,再点击显示出来的cell,跳转页面时searchBar并没有跟着view向左滑动,而是停留在原来的位置,如图一。
原因:
UISearchController也是继承自UIViewController的,也就是说UISearchController也有一个自己的View。但是在使用时只把他的searchBar显示在表头而没有把自带的view添加到self.view上,就是未指定哪一个controller显示UISearchController上的自带的View。所以searchBar不会跟着一起移动。
解决方案:在UIViewController中有以下这个属性
/*
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.
*/
@property(nonatomic,assign) BOOL definesPresentationContext NS_AVAILABLE_IOS(5_0);
大概是这个属性确定了那个父控制器的View,将会以优先于UIModalPresentationCurrentContext这种呈现方式来展现自己的View。如果没有父控制器设置这一属性,那么展示的控制器将会是root view controller。
我们需要将上面那个属性设置YES,告诉系统我们需要将UISearchControoller展示到当前的tableViewController上。
修改代码:
- (void)loadSearchController {
_searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
_searchController.searchResultsUpdater = self;
_searchController.delegate = self;
[_searchController.searchBar sizeToFit];
self.tableView.tableHeaderView = _searchController.searchBar;
_searchController.dimsBackgroundDuringPresentation = NO;
// Present 时隐藏导航栏 该属性默认也为YES
_searchController.hidesNavigationBarDuringPresentation = YES;
// 增加以下代码
self.definesPresentationContext = YES;
}
问题二:
在没有设置definesPresentationContext时更改NavigationBar的Translucent属性,取消半透明效果。在点击SearchBar,SearchBar会直接弹出界面如图一。设置了definesPresentationContext属性为YES后,点击SearchBar,会出现各种下移64的问题,如图二和图三。
原因:
导航栏的NavigationBar的Translucent属性默认为YES就是默认是半透明效果的,将其改为NO之后,原有的布局会发生变化。弹出界面的原因是没有告诉系统我的SearchBarController是放在当前控制器中的,加上取消半透明后界面原有的约束发生了变化,所以searchBar就弹走了,其实就是向上多偏移了64。第二种情况的是没有设置好tableView的contentInset所导致的。
解决方法:
首先像第一个问题一样加上“self.definesPresentationContext = YES;”,确保UISearchController是展示在当前的UITableViewController上的。在设置tableView的contentInset属性时,一开始采用的是单纯的“self.tableView.contentInset = UIEdgeInsetsZero;”,就单单这样写还是有问题的,在searchBar成为第一响应者的时候,会发现tableView的位置比你预期的位置向上偏移了20个像素,如图四。
20个像素,这不就是状态栏搞的鬼吗,所以在搜索状态的时候tableView应该向下偏移20个像素点。判断是否是处于搜索状态可以用UISearchController的active属性。我们也可以把这段代码放在viewWillLayoutSubviews中,毕竟是要按照不同的情况设置不同的contentInset,系统在布局子控件的时候也会调用这个方法(必须要先super一下)。
增加代码:
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
if (self.searchController.isActive) {
self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0);
} else {
self.tableView.contentInset = UIEdgeInsetsZero;
}
}
总结:
上面的内容看起来或许有点混乱,这里基本是有关布局的问题。
解决的方法都围绕着“self.definesPresentationContext = YES;”(present控制器展示在当前控制器而非默认的根控制器)。将导航条半透明属性设为NO之后,将会系统原有的布局,想达到自己的期望需要修改“self.tableView.contentInset”。其实,这种方法解决的不是很好,在动画的时候会感觉出contentInset的变化导致tableView瞬移,仔细看是有一瞬间不足,如果读者有什么办法可以解决此问题,可以在评论处提一下。(๑•̀ㅂ•́)و✧