我正在尝试设置搜索显示控制器来处理来自Web服务的异步结果。我已经掌握了基本功能,但遇到了一个我无法弄清楚的奇怪问题。
似乎为异步操作搜索显示控制器,你真的需要做两件事:
我正在做这两件事,但我看到的是搜索显示控制器正在重新加载输入到搜索栏中的第一个字符上的表,即使我按照#1返回NO。它不会在输入的后续字符上重新加载。
所以,我的问题是:如何在用户输入时让搜索显示控制器不再尝试重新加载表格? (特别是输入的第一个字符)
我已经看到这个问题被提到作为其他几个问题的一部分,但我没有看到问题的直接答案。在我采用一堆UI修改工作之前,我想了解发生了什么或者我做错了什么。
这是我的代码的快速提炼,以显示问题。当我运行它并在搜索栏中输入“abcde”时,在输入“a”后,结果显示为“#0”,“a#2”等。在我点击搜索按钮之前,它们不会再次更新那么你会看到“abcde#0”,“abcde#1”等。当然,在我点击搜索按钮之前,所需的结果都没有发生。
#pragma mark -
#pragma mark UISearchDisplayController Delegate Methods
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
return NO;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
return NO;
}
#pragma mark -
#pragma mark UISearchBarDelegate Methods
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[self.searchDisplayController.searchResultsTableView reloadData];
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 20;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [self.searchDisplayController.searchBar.text stringByAppendingFormat:@" #%d", indexPath.row];
return cell;
}
谢谢! (顺便说一句,这是我在这里提出的第一个问题 - 请告诉我,如果我错过任何礼仪要点:)
答案 0 :(得分:15)
这就是UISearchDisplayController(SDC)的工作方式。当用户将第一个字符输入searchBar时,第一次加载并显示searchTable,导致其加载。方法“... shouldReloadTableForSearchString”和“... shouldReloadTableForSearchScope”允许您控制searchTable是否在后续字符或范围更改时自动重新加载。
我已完成以下两项工作,以便为第一个角色提供良好的用户体验。轻微的免责声明:我确实有这两种方法都可以实现,但这只是我记忆中实现的框架。我可能错过了一个细节,但这应该让你非常接近。
选项1:在输入第一个字符时,在searchTable中显示“加载”单元格。
此选项允许SDC在用户键入第一个字符时显示searchResultsTableView,显示当前搜索/过滤操作的状态
- 添加iVar
BOOL isLoading
- 添加iVar
UITableView *searchTableView
在searchDisplayController:didLoadSearchResultsTableView
- 设置
searchTableView = tableView
在shouldReloadTableForSearchString/Scope
- 设置
isLoading = YES
- 调用您的方法在后台加载数据
- 返回NO
:
- 设置
isLoading = NO
[searchTableView reloadData]
在各种tableView委托方法中,如果当前搜索结果或结果在后台加载,则响应您希望显示状态的方式。我做的是:
- 如果有当前搜索结果,则显示结果(即使在后台加载/过滤)
- 如果没有搜索结果且
isLoading == NO
返回1行并在单元格中显示“不匹配”- 如果没有搜索结果且
isLoading == YES
返回1行并且在单元格中显示搜索活动(我通常使用UIActivityIndicatorView)
选项2:隐藏searchTableView并在其中显示叠加视图,直到加载搜索结果
此选项在首次加载时隐藏searchTableView,仅在搜索/过滤器完成时重新显示。我将其定义为选项1的附加内容,因为它们可以一起完成,但如果您隐藏表并显示叠加层,则可以优化您可能不关心在searchResultsTableView中显示搜索活动的内容。
- 与选项1相同
- 添加iVar
UIView *searchTableOverlayView
在searchDisplayController:didLoadSearchResultsTableView
- 与选项1相同
- 创建一个UIView,用作代替searchTableView的叠加层,其中包含适合您应用的任何用户界面,并将其设置为
searchTableOverlayView
在searchDisplayController:didUnloadSearchResultsTableView
- 发布
searchTableOverlayView
:didShowSearchResultsTableView (may be able to do this in
searchDisplayController:willShowSearchResultsTableView`
- 如果要显示搜索结果或
isLoading == NO
seachTableOverlayView.hidden == YES
- else(if
isLoading == YES
)
searchTableOverlayView.frame == searchResultsTableView.frame
- 将
的子视图seachTableOverlayView
添加为searchTableVIew.superview
searchTableView.hidden = YES
当您的后台过滤器完成时
- 与选项1相同
- 如果要显示searchResults
searchTableCoverView.hidden = YES
searchResultsTableView.hidden = NO
- 否则
searchResultsTableView.hidden = YES
searchTableCoverView.hidden = NO
在各种tableView委托方法中,如果当前搜索结果或结果在后台加载,则响应您希望显示状态的方式。我做的是:
- 与选项1相同
答案 1 :(得分:0)
不幸的是,我相信这就是UISearchDisplayController
的功能。如果您想要请求不同的功能选项,您应该向Apple提交错误报告。
另一种方法是编写自己的UISearchBar
和UITableView
组合,类似于UISearchDisplayController
的工作方式,然后您就能获得更好的控制权。
希望这有帮助!
答案 2 :(得分:0)
当我遇到同样的问题时,我试图在搜索结果视图中添加叠加视图。那对我没有帮助。看起来Apple改变了行为,我看到细胞分离器在我的视野中闪耀。最后我提出了一个很好的方法。
首先,我的异步搜索类拥有自己的叠加层,进度和其他视图。 UISearchDisplayController仅用于启动,结束委托方法调用和坚持默认搜索流程。 为了显示视图,我使用了任何子视图,我可以将搜索视图放在(作为初始化调用):
newView.frame = frame;
[view addSubview:newView];
然后在更改搜索进度视图时使用子视图:
if (view == currentView)
return;
view.frame = currentView.frame;
view.alpha = [self getAlphaValueForView:view];
UIView * superView = [currentView superview];
[currentView removeFromSuperview];
currentView = view;
[superView addSubview:currentView];
当我开始在默认导航例程(导航控制器)中使用我的搜索内容控制器时,出现空搜索结果表视图闪烁的问题。
所以为了解决这个问题,我开始使用导航而不是内容控制器(在这种情况下是默认搜索显示控制器激活),而是一个空控制器。我使用空控制器视图作为搜索视图的子视图。
总的来说:不要在导航中使用UISearchDisplayController的内容视图控制器。使用存根视图控制器。然后使用它的视图将您的视图作为子视图。
对我来说很棒。
答案 3 :(得分:0)
隐藏self.searchDisplayController.searchResultsTableView,直到用户按下搜索按钮
- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView;
{
tableView.hidden = YES;
}
用户按下搜索键后,搜索结果就绪,请将搜索结果表显示为
self.searchDisplayController.searchResultsTableView.hidden = NO;
[self.searchDisplayController reloadData]
此解决方法适用于我。
答案 4 :(得分:-1)
也许您需要实现UISearchDisplayController
然后执行此功能:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText