【问题标题】:UISearchDisplayController with no results tableView?UISearchDisplayController 没有结果tableView?
【发布时间】:2009-07-31 18:44:44
【问题描述】:

通常,UISearchDisplayController 在激活时会使 tableView 变暗并聚焦 searchBar。一旦您在 searchBar 中输入文本,它就会创建一个在 searchBar 和键盘之间显示的 searchResultsTableView。当加载/显示/隐藏/卸载第二个 UITableView 时,将调用 searchDisplayController 的委托。通常它会在输入时显示实时搜索结果或自动完成条目。

在我的应用程序中,我想搜索网络服务,但我不想为用户输入的每个字母调用网络服务。因此,我想完全禁用 searchResultsTableView 并在他输入文本时保持变暗的黑色覆盖。一旦他点击搜索按钮,我就会触发搜索(带有加载屏幕)。

只为 searchResultsTableView 返回零行看起来不太好,因为它显示一个空的 searchResultsTableView 并带有“无结果”消息。我试图在表格出现时隐藏它(searchDisplayController:didLoadSearchResultsTableView:),它起作用了,但是变黑的灰色叠加层也被隐藏了,因此底层的 tableView 再次完全可见。

除了从头开始重新创建 UISearchDisplayController 功能之外还有什么想法吗?

【问题讨论】:

    标签: iphone objective-c uisearchbar searchdisplaycontroller


    【解决方案1】:

    这是我刚刚发现的一个小技巧 并且您必须在编辑搜索字符串时返回 0 个结果

    - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
    {
        savedSearchTerm = searchString;
    
        [controller.searchResultsTableView setBackgroundColor:[UIColor colorWithWhite:0.0 alpha:0.8]];
        [controller.searchResultsTableView setRowHeight:800];
        [controller.searchResultsTableView setScrollEnabled:NO];
        return NO;
    }
    
    - (void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView
    {
        // undo the changes above to prevent artefacts reported below by mclin
    }
    

    我想你会弄清楚下一步该做什么

    【讨论】:

    • 正是我想要的。非常感谢!
    • 对我来说是第一次工作,但如果你搜索,单击 x 清除然后输入更多文本,它会显示所有带有不透明黑色背景和白色分隔线的行。我猜它可能是 UITableCellViews,所以我将它添加到你的函数中并且它起作用了: for (UIView *subview in self.searchDisplayController.searchResultsTableView.subviews) { [subview removeFromSuperview]; }
    • 也值得把'controller.searchResultsTableView.scrollEnabled = NO;'也在那里
    • 出色的解决方案。也 +1 给@Chris。考虑到这正是地图应用程序的工作方式,为什么 Apple 没有将其作为您可以选择的设置似乎真的很愚蠢。
    • 需要记住的其他几点:(1) 点击此表不会导致UISearchDisplayController 被关闭(我必须使用UITapGestureRecognizer)。 (2) iPad 背景颜色 alpha 应为 ~0.5
    【解决方案2】:

    你试过了吗:

    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_lookup:) object:nil];
    [self performSelector:@selector(_lookup:) withObject:txt afterDelay:0.20];
    

    这样,如果用户在 1/5 秒内键入另一个字符,您只需进行一次网络调用。

    【讨论】:

    • 使用object:nil,取消调用真的会匹配吗?如果您没有任何其他执行请求,您可能最好调用普通的旧 [NSObject cancelPreviousPerformRequestsWithTarget:self]。
    【解决方案3】:

    最后似乎没有一个效果很好,所以我想出了以下方法(当你准备好显示结果时,你必须调用 removeTableHeader):

    - (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
        [self setTableHeader];
    }
    
    - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
        [self setTableHeader];
    }
    
    - (void)setTableHeader {
        UIView *headerView = [[UIView alloc] initWithFrame:self.searchDisplayController.searchResultsTableView.frame];
        headerView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.8];
    
        [self.searchDisplayController.searchResultsTableView setBackgroundColor:[UIColor clearColor]];
        [self.searchDisplayController.searchResultsTableView setScrollEnabled:NO];
        [self.searchDisplayController.searchResultsTableView setTableHeaderView:headerView];
    
        [headerView release];
    }
    
    - (void)removeTableHeader {
        [self.searchDisplayController.searchResultsTableView setBackgroundColor:[UIColor whiteColor]];
        [self.searchDisplayController.searchResultsTableView setScrollEnabled:YES];
        [self.searchDisplayController.searchResultsTableView setTableHeaderView:nil];
    }
    

    显然,它使表格透明,添加与表格大小相同的黑色/半透明表格标题,并禁用表格滚动,因此您无法越过或超过标题。作为奖励,您可以在标题视图中添加一些内容(“请稍候...”或活动指示器)。

    【讨论】:

    • 这种方法有效,但您无法单击标题以关闭
    • 这个解决方案是我发现的最干净、最有效的解决方案。这里其他解决方案的主要问题是,当“假”阴影覆盖可见并且您关闭搜索界面时,iOS 会强制 tableView 变得不透明并且屏幕快速闪烁白色,这很难看。此实现不会发生这种情况。 @chaiwalla,如果您想模仿默认的点击关闭行为,只需将 UITapGestureRecognizer 添加到 headerView 并在回调中调用 setActive:animated: on searchDisplayController。
    • 只是与样式相关的备注。您可能想使用showTableHeader 而不是setTableHeader,因为在这种情况下它不是真正的二传手。
    • +1 这是恕我直言,最优雅的解决方案。为了修正@chaiwalla 的言论,我在HeaderView 中使用了一个UIButton,然后为IBAction 调用[searchDisplayController setActive:NO],从而在触摸该区域时关闭搜索。
    【解决方案4】:

    遇到和你一样的问题,我是通过a)在开始搜索时将searchResultsTableView的alpha设置为0,然后通过b)添加/删除来处理的overlayView 到 viewController 的视图。对我来说就像一个魅力。

    @interface MyViewController()
    //...
    @property(nonatomic, retain) UIView *overlayView;
    //...
    @end
    
    @implementation MyViewController
    @synthesize overlayView = _overlayView;
    
    //...
    
    - (void)viewDidLoad
    {
        //...
    
        //define your overlayView
        _overlayView = [[UIView alloc] initWithFrame:CGRectMake(0, 44, 320, 480)];
        _overlayView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.8];
    }
    
    //hide the searchResultsTableView
    - (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller
    {
        self.searchDisplayController.searchResultsTableView.alpha = 0.0f;
    }
    
    //when ending the search, hide the overlayView
    - (void) searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller
    {
        [_overlayView removeFromSuperview];
    }
    
    //depending on what the user has inputed, add or remove the overlayView to the view of the current viewController 
    - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
    {   
    
        if ([searchString length]>0) 
        {
            [self.view addSubview:_overlayView];
        }
        else
        {
            [_overlayView removeFromSuperview];
        }
    
        return NO;
    }
    
    @end
    

    【讨论】:

    • 我比公认的答案更喜欢这个解决方案;谢谢!干净多了
    【解决方案5】:

    在您的 UISearchDisplayDelegate(通常是您的自定义 UITableViewController 子类)中实现以下方法就足够了

    - (BOOL) searchDisplayController: (UISearchDisplayController *) controller shouldReloadTableForSearchString: (NSString *) searchString
    {
        [self startMyCustomWebserviceSearchAsBackgroundProcessForString: searchString]; //starts new NSThread
        return NO; 
    }
    

    你试过了吗?

    【讨论】:

    • 这会阻止 searchDisplayController 发送 [searchResultsTableView reload],但不幸的是 searchResultsTableView 仍然显示(“无结果”消息)
    • 在这种情况下,恐怕无法修改 UISearchDisplayController 的默认行为...抱歉
    • 我昨天纯属偶然注意到,YouTube 应用程序完全符合我的要求。不幸的是,我还没有找到任何好的方法(除了创建 UISearchDisplayController)。
    【解决方案6】:

    以下基于 user182820 的代码是我的版本。我隐藏了 UISearchDisplayController 的表格视图。当在搜索框中输入一个字符时,我会放置一个“变暗视图”,因此看起来 UISearchDisplayController 的“变暗视图”从未消失,然后在搜索完成后将其删除。如果您输入一些字符并按取消,表格视图会短暂变为白色,我不知道如何解决这个问题。

    - (void)viewDidLoad {
        ...
        tableViewMask=[UIView new];
        tableViewMask.backgroundColor = [UIColor blackColor];
        tableViewMask.alpha = 0.8;
    }
    
    - (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller{
        tableViewMask.frame=CGRectMake(self.tableView.frame.origin.x, self.tableView.frame.origin.y+controller.searchBar.frame.size.height, self.tableView.frame.size.width, self.tableView.frame.size.height-controller.searchBar.frame.size.height);
        controller.searchResultsTableView.hidden=YES;
    }
    
    - (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller{
        [tableViewMask removeFromSuperview];
    }
    
    - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString{
        if (searchString.length==0)
            [tableViewMask removeFromSuperview];
        else 
            [self.tableView addSubview:tableViewMask];
        [searchText autorelease];
        searchText=[searchString retain];
        return NO;
    }   
    

    【讨论】:

      【解决方案7】:

      就这么简单的做起来怎么样:

      - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
      {
      self.searchDisplayController.searchResultsTableView.hidden=YES;
      return YES;
      }
      

      对我来说很好用..

      【讨论】:

      • 这只是部分起作用,在我的情况下,背景变暗,一旦我开始输入变暗的背景就会被删除并显示底层的 tableview
      【解决方案8】:

      我找到了一个更好的方法,因为“最佳答案”存在一个错误 - 滚动黑色背景表格时将显示分隔符和“无结果”。

      - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
      
          controller.searchResultsTableView.backgroundColor = [UIColor blackColor];
          controller.searchResultsTableView.alpha = 0.8;
          controller.searchResultsTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
      
          for(UIView *subview in tableView.subviews) {
              if([subview isKindOfClass:UILabel.class]) {
                  subview.hidden = YES;
              }
          }
      
          return NO;
      }
      
      - (void) searchBarSearchButtonClicked:(UISearchBar *)searchBar {
      
          self.searchDisplayController.searchResultsTableView.backgroundColor = [UIColor whiteColor];
          self.searchDisplayController.searchResultsTableView.alpha = 1;
          self.searchDisplayController.searchResultsTableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
      
          for(UIView *subview in tableView.subviews) {
              if([subview isKindOfClass:UILabel.class]) {
                  subview.hidden = NO;
              }
          }
      
          // search results and reload data ....
      }
      

      【讨论】:

      • 您可以禁用滚动并绕过您提到的“错误”:controller.searchResultsTableView.scrollEnabled = NO;
      【解决方案9】:

      所有现有的答案都过于复杂。您只需立即隐藏结果表视图即可逃脱。

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

      【讨论】:

        【解决方案10】:

        我想我为这个问题找到了更好的实现。之前的所有答案都正确显示了与搜索前 UITableView 相同的暗色视图,但每个解决方案都缺少点击该区域以取消搜索的功能。

        因此,我认为这段代码效果更好。

        首先,创建一个像searchButtonTapped这样的BOOL来表示搜索按钮是否被点击。默认为否。

        然后:

        - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
        if (!searchButtonTapped) {        
            // To prevent results from being shown and to show an identical look to how the tableview looks before a search
            [controller.searchResultsTableView setBackgroundColor:[UIColor clearColor]];
            [controller.searchResultsTableView setRowHeight:160];
            self.searchDisplayController.searchResultsTableView.scrollEnabled = NO;
        } else {
            // Restore original settings
            [controller.searchResultsTableView setBackgroundColor:[UIColor whiteColor]];
            [controller.searchResultsTableView setRowHeight:44];
            self.searchDisplayController.searchResultsTableView.scrollEnabled = YES;
        }
        
        return YES;
        }
        

        根据其他答案,现在应该很清楚了。确保在用户点击“搜索”按钮时也恢复原始设置。

        此外,在 cellForIndexPath 方法中添加:

        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        cell.contentView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.8];
        

        为了创建在输入文本之前显示的相同的暗色视图。确保将这些属性应用于正确的单元格,即检查哪个 UITableView 处于活动状态以及用户没有点击“搜索”按钮。

        然后,至关重要的是,在 didSelectRowAtIndexPath 中:

        if (tableView == self.searchDisplayController.searchResultsTableView) {
            if (searchButtonTapped) {
                   // Code for when the user select a row after actually having performed a search
            {
        else 
            [self.searchDisplayController setActive:NO animated:YES];
        

        现在用户可以点击灰色区域,这不会导致 UITableViewCell 的可见选择,而是取消搜索。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-02-19
          • 1970-01-01
          • 1970-01-01
          • 2014-01-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多