7

我正在尝试设置一个搜索显示控制器来处理来自网络服务的异步结果。我已经掌握了基本知识,但遇到了一个我无法弄清楚的非常奇怪的问题。

似乎要为异步设置搜索显示控制器,您实际上只需要做两件事:

  1. 为 searchDisplayController:shouldReloadTableForSearchString 返回 NO,并且
  2. 处理 searchBarSearchButtonClicked 并关闭表重新加载自己。

我正在做这两件事,但我看到的是搜索显示控制器正在重新加载输入到搜索栏中的第一个字符的表格,即使我按照 #1 返回 NO。它不会在输入的后续字符上重新加载。

所以,我的问题是:如何防止搜索显示控制器在用户键入时尝试重新加载表格?(特别是在输入的第一个字符上)

我已经看到这个问题是作为其他几个问题的一部分提到的,但我还没有看到这个问题的直接答案。在我求助于一堆 UI 修改来解决它之前,我想了解发生了什么或我做错了什么。

这是我的代码的快速提炼以显示问题。当我运行它并在搜索栏中输入“abcde”时,在我输入“a”后,结果显示为“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;
}

谢谢!(顺便说一句,这是我在这里提出的第一个问题——如果我错过任何礼仪要点,请告诉我:)

4

5 回答 5

15

这正是 UISearchDisplayController (SDC) 的工作方式。当用户在 searchBar 中输入第一个字符时,searchTable 被加载并首次显示,导致它被加载。方法 "...shouldReloadTableForSearchString" 和 "...shouldReloadTableForSearchScope" 允许您控制 searchTable 是否在后续字符或范围更改时自动重新加载。

我已经完成了以下两项操作,以在第一个字符上提供良好的用户体验。轻微免责声明:我确实有这两种方法的实现,但这只是我记忆中的一个实现框架。我可能错过了一个细节,但这应该让你非常接近。

选项 1:当输入第一个字符时,在 searchTable 中显示一个“加载”单元格。

此选项允许 SDC 在用户键入第一个字符时显示 searchResultsTableView,显示当前搜索/过滤操作的状态

  1. 在 SDC 委托类定义中

    • 添加 iVarBOOL isLoading
    • 添加 iVarUITableView *searchTableView
  2. searchDisplayController:didLoadSearchResultsTableView

    • searchTableView = tableView
  3. shouldReloadTableForSearchString/Scope

    • isLoading = YES
    • 调用您的方法在后台加载数据
    • 返回否
  4. 当您的背景过滤器完成时:

    • isLoading = NO
    • [searchTableView reloadData]
  5. 如果有当前搜索结果或结果正在后台加载,则在各种 tableView 委托方法中响应您希望如何显示状态。我所做的是:

    • 如果有当前搜索结果,则显示结果(即使在后台加载/过滤)
    • 如果没有搜索结果并isLoading == NO返回 1 行并在单元格中显示“无匹配项”
    • 如果没有搜索结果并isLoading == YES返回 1 行并在单元格中显示搜索活动(我通常使用 UIActivityIndi​​catorView)

选项 2:隐藏 searchTableView 并在其位置显示覆盖视图,直到加载搜索结果

此选项在第一次加载时隐藏 searchTableView,并且仅在搜索/过滤器完成时重新显示它。我将此定义为选项 1 的附加内容,因为它们可以一起完成,但如果您隐藏表格并显示覆盖,则可以优化您可能不关心在 searchResultsTableView 中显示搜索活动的内容。

  1. 在 SDC 委托类定义中

    • 与选项 1 相同
    • 添加 iVarUIView *searchTableOverlayView
  2. searchDisplayController:didLoadSearchResultsTableView

    • 与选项 1 相同
    • 创建一个 UIView 以用作替代 searchTableView 的覆盖,其中包含适合您的应用的任何 UI 并将其设置为searchTableOverlayView
  3. searchDisplayController:didUnloadSearchResultsTableView

    • 释放searchTableOverlayView
  4. 在'searchDisplayController:didShowSearchResultsTableView (may be able to do this insearchDisplayController:willShowSearchResultsTableView`

    • 如果有搜索结果要显示或isLoading == NO
      • seachTableOverlayView.hidden == YES
    • 否则(如果isLoading == YES
      • searchTableOverlayView.frame == searchResultsTableView.frame
      • 添加seachTableOverlayView为子视图searchTableVIew.superview
      • searchTableView.hidden = YES
  5. 当您的背景过滤器完成时

    • 与选项 1 相同
    • 如果有搜索结果要显示
      • searchTableCoverView.hidden = YES
      • searchResultsTableView.hidden = NO
    • 别的
      • searchResultsTableView.hidden = YES
      • searchTableCoverView.hidden = NO
  6. 如果有当前搜索结果或结果正在后台加载,则在各种 tableView 委托方法中响应您希望如何显示状态。我所做的是:

    • 与选项 1 相同
于 2011-03-17T17:41:39.423 回答
0

不幸的是,我相信这就是UISearchDisplayController功能。如果您想请求不同的功能选项,您应该向 Apple 提交错误报告。

另一种方法是编写自己的UISearchBar组合并UITableView类似于UISearchDisplayController工作方式,然后您将获得更好的控制。

希望这可以帮助!

于 2011-03-06T15:08:10.957 回答
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 的内容视图控制器。使用存根视图控制器。然后使用它的视图将您的视图作为子视图。

对我来说效果很好。

于 2012-12-16T21:16:03.570 回答
0

隐藏 self.searchDisplayController.searchResultsTableView 直到用户按下搜索按钮

- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView;
{
    tableView.hidden = YES;
}

用户按下搜索键,搜索结果准备好后,使搜索结果表可见

self.searchDisplayController.searchResultsTableView.hidden = NO;
[self.searchDisplayController reloadData]

这种解决方法对我有用。

于 2013-07-22T06:41:30.533 回答
-1

也许你需要实现UISearchDisplayController然后这个功能:

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
于 2011-03-03T04:00:41.837 回答