【问题标题】:UISearchDisplayContoller – can't prevent table reload on typing in search barUISearchDisplayController – 无法阻止在搜索栏中输入时重新加载表格
【发布时间】:2010-10-11 05:32:13
【问题描述】:

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

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

  1. 返回 NO searchDisplayController:shouldReloadTableForSearchString, 和
  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;
}

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

【问题讨论】:

  • 您能展示一下您是如何设置搜索栏的吗?您是否正确设置了委托?你什么时候设置的 - 也许它设置为 nil 因为你期望设置的东西不是
  • 这一切都在 IB 中设置...创建了一个简单的项目,放在表格视图中,在表格标题位置放置一个搜索栏,然后连接所有内容。我在上面的每种方法中都有 nslog 行,并且一切都按我的预期启动。除了在搜索栏的第一个文本更改时开始重新加载表格之外,它真的很完美。
  • 你有没有弄清楚这是关于什么的?您可以编辑您的帖子并关闭问题吗?
  • 不,我从来不知道为什么会这样。我还想知道——我应该让这个问题悬而未决吗?
  • stackoverflow.com/a/8650915/435635 恕我直言也是一个不错的选择

标签: iphone uitableview uisearchbar uisearchdisplaycontroller


【解决方案1】:

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

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

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

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

  1. 在 SDC 委托类定义中

    • 添加 iVar BOOL isLoading
    • 添加 iVar UITableView *searchTableView
  2. searchDisplayController:didLoadSearchResultsTableView

    • 设置searchTableView = tableView
  3. shouldReloadTableForSearchString/Scope

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

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

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

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

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

  1. 在 SDC 委托类定义中

    • 与选项 1 相同
    • 添加 iVar UIView *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 相同

【讨论】:

  • 我希望我只是遗漏了一些细节,但我想我同意你和瀑布先生的观点——它就是这样工作的(尽管我仍然认为它为异步搜索引入了不必要的混乱)。我已经将这个项目搁置了一段时间,但最终可能会得到类似于您的选项 2 的内容。感谢您抽出宝贵时间来编写。很有帮助。
  • 第 3 步和第 4 步让我的代码正常工作。非常感谢!
【解决方案2】:

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

替代方法是编写自己的UISearchBarUITableView 组合,类似于UISearchDisplayController 的工作方式,然后您将获得更好的控制。

希望这会有所帮助!

【讨论】:

    【解决方案3】:

    当我遇到同样的问题时,我尝试在搜索结果视图上放置一个覆盖视图。那对我没有帮助。看起来 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 的内容视图控制器。使用存根视图控制器。然后使用它的视图将您的视图作为子视图。

    对我来说效果很好。

    【讨论】:

      【解决方案4】:

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

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

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

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

      此解决方法对我有用。

      【讨论】:

        【解决方案5】:

        也许你需要实现UISearchDisplayController然后这个函数:

        - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-25
          • 2013-09-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-10-10
          相关资源
          最近更新 更多