UISearchDisplayController – 如何预载searchResultTableView
我想显示一些默认的内容,当用户点击search栏,但在任何文本input之前。
我有一个使用settext的解决scheme:
- (void) searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller { [searchDisplayController.searchBar setText:@" "]; }
这工作,但它不优雅,search栏中的提示文字消失。
有没有更好的方法来预加载到UISearchDisplayController的SearchResultTableView数据,而不必自己实现整个UISearchfunction在自定义控制器?
要获得所需效果的演示,请查看Safari的search框,如果点击它,search界面将打开,并显示以前的search。
好的,我有。 用一些数据预加载你的数据源,并做下面的黑客(没有任何非法),你会得到的tableView显示。 请注意,可能会进行一些清理工作,但是这会显示您的默认数据。
在视图控制器的viewDidLoad比拥有UISearchBar:
[super viewDidLoad]; [self.searchDisplayController.searchResultsTableView reloadData]; // whatever you named your search bar - mine is property named searchBar CGRect testFrame = CGRectMake(0, 20, self.searchBar.frame.size.width, 100); self.searchDisplayController.searchResultsTableView.frame = testFrame; [self.searchBar.superview addSubview:self.searchDisplayController.searchResultsTableView];
这是发生了什么事情:
UISearchBar不想显示searchResultsTableView,直到开始编辑。 如果你触摸tableView(例如reloadData),它将加载并在那里,坐在frame = CGRectZero的内存中。 你给它一个适当的框架,然后将其添加到searchBar,等瞧。
我validation了这是正确的显示searchView的超视图和tableView的正确加载后的tableview的超视图 – 他们有相同的超级视图。 所以,我回去并早日将tableView添加到superview中,并且确实显示出来了。 对我来说,它显示变暗(也许上面的另一个视图?alpha设置较低?),但仍然可点击。 我没有更进一步,但是这绝对让你的tableView显示没有任何用户交互。
请享用,
达米安
我发现这个问题更好的解决scheme,它似乎在iOS 6和7完美的工作。虽然它仍然是一个黑客,它是一个更清洁和未来certificate黑客比上述。 其他的解决scheme不能一致地工作,并阻止一些UISearchDisplayDelegate方法的发射! 此外,我有复杂的插入问题,我不能用上述方法解决。 其他解决scheme的主要问题是,他们严重混淆了UISearchDisplayController的内部。 我的解决scheme是基于观察UISearchDisplayContoller是一个UISearchbarDelegate和结果表的自动调整和显示可以通过模拟search字段中的按键触发! 所以:
- (void) searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller { if ([controller respondsToSelector: @selector(searchBar:textDidChange:)]) [(id<UISearchBarDelegate>)controller searchBar: controller.searchBar textDidChange: @" "]; }
这个代码是通过检查它响应UISearchbarDelegate方法来防止崩溃,并发送空间@“”欺骗UISearchDisplayController使用户认为用户键入了一个字母。
现在,如果用户input某个内容然后将其删除,表格将会再次变暗。 其他解决scheme尝试通过在searchDisplayController:didHideSearchResultsTableView:方法中执行某些操作来解决此问题。 但是这对我没有意义,因为当你取消search时,它将需要真正隐藏你的结果表,你可能需要在这种情况下运行代码。 我的这个部分的解决scheme是子类(注意你可能可以使用一个方法Swizzled类别,使其在任何地方工作,如果您的项目需要):
// privately declare protocol to suppress compiler warning @interface UISearchDisplayController (Super) <UISearchBarDelegate> @end // subclass to change behavior @interface GMSearchDisplayController : UISearchDisplayController @end @implementation GMSearchDisplayController - (void) searchBar: (UISearchBar *) searchBar textDidChange: (NSString *) searchString { if (searchString.length == 0) searchString = @" "; if ([super respondsToSelector: @selector(searchBar:textDidChange:)]) [super searchBar: searchBar textDidChange: searchString]; } @end
此代码通过截取textDidChange委托方法并将空string更改为空string@“”来防止在空search栏上发生的正常隐藏/调暗。 如果你正在使用这个第二位的代码,那么你可以修改第一位来传递一个零而不是@“”,因为这第二位会为你做所需的转换。
在我自己的项目中,我需要处理用户键入空格的情况,所以不是上面的@“”,而是使用了一个定义的标记:
// arbitrary token used internally #define SEARCH_PRELOAD_CONDITIONAL @"_#preresults#_"
然后通过将其转换回零string来处理它:
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString { if ([searchString isEqualToString: SEARCH_PRELOAD_CONDITIONAL]) searchString = nil; }
请享用! 🙂
iOS 7工作解决scheme:
// When the tableView is hidden, put it back - (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller { [self.searchDisplayController.searchResultsTableView reloadData]; controller.searchResultsTableView.hidden = NO; // Also, remove the dark overlay for (UIView *v in [[controller.searchResultsTableView superview] subviews]) { // This is somewhat hacky.. if (v.alpha < 1) { [v setHidden:YES]; } } } -(void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView { [self.searchDisplayController.searchResultsTableView reloadData]; if (self.searchDisplayController.active == YES) { tableView.hidden = NO; } }
我有解决scheme。 插入这三个方法。你必须让tableview预装数据才能工作。 我有这个代码在我的代码工作,所以它必须为你工作,只要你已经预装的数据,你正在使用search显示控制器。
- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller { CGRect testFrame = CGRectMake(0, self.notesSearchBar.frame.size.height, self.notesSearchBar.frame.size.width, self.view.frame.size.height - self.notesSearchBar.frame.size.height); self.searchDisplayController.searchResultsTableView.frame = testFrame; [self.notesSearchBar.superview addSubview:self.searchDisplayController.searchResultsTableView]; // [self.view addSubview:self.searchDisplayController.searchResultsTableView]; controller.searchResultsTableView.hidden = NO; } -(void) searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView { CGRect testFrame = CGRectMake(0, self.notesSearchBar.frame.size.height, self.notesSearchBar.frame.size.width, self.view.frame.size.height - self.notesSearchBar.frame.size.height); self.searchDisplayController.searchResultsTableView.frame = testFrame; [self.notesSearchBar.superview addSubview:self.searchDisplayController.searchResultsTableView]; // [self.view addSubview:self.searchDisplayController.searchResultsTableView]; controller.searchResultsTableView.hidden = NO; } -(void) searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller { controller.searchResultsTableView.hidden = YES; }
这适用于iOS 8:
- (void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView { self.searchDisplayController.searchResultsTableView.hidden = NO; } - (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller { self.searchDisplayController.searchResultsTableView.hidden = NO; [self.searchDisplayController.searchResultsTableView.superview.superview bringSubviewToFront:self.searchDisplayController.searchResultsTableView.superview]; CGRect frame = self.searchDisplayController.searchResultsTableView.frame; self.searchDisplayController.searchResultsTableView.frame = CGRectMake(frame.origin.x, 64, frame.size.width, frame.size.height); }
但是,我不喜欢这个破解,并通过我自己的实现(UITearchBar与UITableView)取代了searchDisplayController。
我用UISearchController在iOS 9中testing了以下内容。
默认情况下,只要UISearchBar中没有文本,所显示的表就是你的原始表视图(从这里开始称为originalTableView )。 根据dimsBackgroundDuringPresentation
的值,这可能有也可能没有黑色透视层。
一旦用户input任何文本到UISearchBar中,新的表格视图的内容就会显示出来(我将把它称为searchTableView )。
请注意,在这两种解决scheme中,我都以类似苹果在这个例子中的方式来实现UISearchController。 即有两个独立的UITableViewController负责显示数据。
解决scheme1:复杂的实现,更stream畅的animation
为了更stream畅的animation:
- 实现UISearchControllerDelegate的willPresentSearchController和willDismissSearchController方法。
- 在willPresent中,更新您的originalTableView的数据以准备好显示您想要的任何零文本数据,然后调用
reloadData()
。 - 在willDismiss中,恢复进程以显示原始内容并调用
reloadData()
。
例:
// here tableView refers to originalTableView extension ViewController: UISearchControllerDelegate { func willPresentSearchController(searchController: UISearchController) { data = ["A", "B", "C"] tableView.reloadData() } func willDismissSearchController(searchController: UISearchController) { data = ["a", "b", "c"] tableView.reloadData() } }
在这个虚构的例子中,当用户不关注UISearchBar时,数据显示为a,b,c
,但是一旦用户点击UISearchBar,显示为A,B,C
。
解决scheme2:快速实施,波涛汹涌的animation
而不是在originalTableView和searchTableView中实现search控制器的逻辑,您可以使用此解决scheme来简单地显示searchTableView,即使它默认情况下是隐藏的。
很可能,您已经在实施UISearchResultsUpdating协议。 通过在该方法中简单地调用tableView.hidden = false
,你应该得到你以后的行为; 尽pipe不如恒星animation。
// here tableView refers to searchTableView extension SearchViewController: UISearchResultsUpdating { func updateSearchResultsForSearchController(searchController: UISearchController) { tableView.hidden = false filterData(text: searchController.searchBar.text!) tableView.reloadData() } }
为什么不看看Xcode中的TableSearch项目? 它或多或less地解决您的需求。 它在开始时显示一个表格,并在search字段被点击时显示出来。 在Xcode 4的帮助文档和API参考中检查TableSearch。
另外看看这几乎做你需要一个UISearchBar和一个UITableView。 我更喜欢这种方法。 调整它。
为了进一步解决您的需求,我build议使用两个数据源。 一个拥有所有的内容(这是你将在最开始显示的)和一个持有过滤的search结果。 现在继续,清空第一个数据源,并用第二个数据源的内容来填充它,以存储和隐藏之前search的结果。 继续这种方式。 在您的任务的TableSearch代码中使用此方法。
这是预先填充searchController的一种方法。
// 1.一旦用户input文字,保存以前的search结果
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString { // save searchString return YES; }
// 2.在启动时加载之前的searchstring
- (void)viewDidLoad { // create data source for table view // searchData may be a NSMutableArray property defined in your interface self.searchData = // search your master list for searchString // or create your own list using any search criteria you want // or you may act depending on user preference if(!showPreviousSearch) { // [searchData removeAllObjects]; } }
//询问时提供正确的数据源
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { ... } NSMutableArray *dataSource = nil; if (tableView == [[self searchDisplayController] searchResultsTableView]) { dataSource = self.searchData; } else { dataSource = self.masterData; } ... return cell; }
// 希望这可以帮助。
谢谢