【问题标题】:Show UISearchController's SearchResultsController on SearchBar Tap在 SearchBar Tap 上显示 UISearchController 的 SearchResultsController
【发布时间】:2015-03-22 16:17:38
【问题描述】:

我使用的是 UISearchController 而不是 UISearchDisplayController,我想立即在 SearchBar Tap 上显示 SearchResultController。现在它是这样显示的(当我点击搜索栏时):

【问题讨论】:

    标签: ios uisearchcontroller


    【解决方案1】:

    当结果为空时,UISearchControllerviewController 仍处于隐藏状态。这就是为什么我们必须使用UISearchControllerDelegatewillPresentSearchController:来摆弄我们的方式

    在初始化 self.searchController 之后,让你的 ViewController 符合 `UISearchControllerDelegate:

    self.searchController.delegate = self;
    

    在您的 ViewController 中实现 willPresentSearchController:

    - (void)willPresentSearchController:(UISearchController *)searchController
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            searchController.searchResultsController.view.hidden = NO;
        });
    }
    

    异步调度是必要的,否则它将被内部行为覆盖。您可以在这里花哨并使用动画让表格视图淡入。

    此外,为了理智,实施didPresentSearchController:

    - (void)didPresentSearchController:(UISearchController *)searchController
    {
        searchController.searchResultsController.view.hidden = NO;
    }
    

    【讨论】:

    • 它仅在第一次点击搜索结果控制器中的任何内容时才有效,当您再次点击搜索栏时它不会显示搜索结果控制器。
    • 您是否尝试过实现计数器委托方法didDismissSearchController:willDismissSearchController:?在这些方法中设置searchController.searchResultsController.view.hidden = YES;
    • 我做了,但对它没有任何影响。
    • 我无法使用示例代码 (developer.apple.com/library/ios/samplecode/…) 重现它。第二次点击时会调用委托方法吗?
    • @tubtub 这对于第一次启动非常有用。如果我们输入一些内容然后完全删除输入的文本,resultsController 会再次隐藏。有没有办法解决这个问题?
    【解决方案2】:

    我发现其他答案因使用dispatch_async 而闪烁。他们使用这个,以便在搜索控制器的内部行为完成后应用他们的更改,但这会留下几个框架,在内部行为被覆盖之前应用内部行为。使用 KVO 可以让我立即覆盖内部行为而不会出现任何闪烁。

    我还发现,当用户点击 ⓧ 按钮清除搜索栏的内容时,其他答案并没有使搜索结果控制器保持可见,这对我来说似乎不正确。

    - (void) viewDidLoad
    {
        ...
        self.searchController.delegate = self;
        [self.searchController.searchResultsController.view addObserver:self forKeyPath:@"hidden" options:0 context:NULL];
    }
    
    - (void)observeValueForKeyPath:(NSString *)keyPath
                          ofObject:(id)object
                            change:(NSDictionary *)change
                           context:(void *)context
    {    
        if ( object == self.searchController.searchResultsController.view &&
             [keyPath isEqualToString:@"hidden"] &&
             self.searchController.searchResultsController.view.hidden &&
             self.searchController.searchBar.isFirstResponder )
        {
            self.searchController.searchResultsController.view.hidden = NO;
        }
    }
    
    - (void) willPresentSearchController:(UISearchController *)searchController
    {
        searchController.searchResultsController.view.hidden = NO;
    }
    
    - (void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
    {
        if ( searchText.length == 0 )
            self.searchController.searchResultsController.view.hidden = NO;
    }
    
    
    - (void) searchBarTextDidEndEditing:(UISearchBar *)searchBar
    {
        self.searchController.searchResultsController.view.hidden = YES;
    }
    

    【讨论】:

    • 到目前为止,这是最有效的答案。观察者是关键(双关语是温和的)
    • 感谢您提供出色的解决方案!但是我可以问你,如果你已经为此目的设置了一个观察者,你为什么要处理 searchBar: textDidChange 方法?
    • 我已经有一段时间没有看到这个了,但看起来观察者只处理不断变化的“隐藏”属性,而 searchBar:textDidChange: 检测到文本的最后一位被删除的时间,并隐藏搜索结果控制器。看起来他们正在完成两件不同的事情。
    【解决方案3】:

    Chris Vasselli 的回答是实现这一点的最简洁方式。

    它在 Swift 3 中

    override func viewDidLoad() {
        super.viewDidLoad()
    
        searchController.delegate = self
        self.searchController.searchResultsController?.view.addObserver(self, forKeyPath: "hidden", options: [], context: nil)
    }
    
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    
        if let someView: UIView = object as! UIView? {
    
            if (someView == self.searchController.searchResultsController?.view &&
                (keyPath == "hidden") &&
                (searchController.searchResultsController?.view.isHidden)! &&
                searchController.searchBar.isFirstResponder) {
    
                searchController.searchResultsController?.view.isHidden = false
            }
    
        }
    }
    
    
    func willPresentSearchController(_ searchController: UISearchController) {
        searchController.searchResultsController?.view.isHidden = false
    }
    
    
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    
        if (searchText.characters.count == 0) {
            searchController.searchResultsController?.view.isHidden = false
        }
    }
    
    
    func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
        searchController.searchResultsController?.view.isHidden = true
    }
    

    【讨论】:

      【解决方案4】:

      我觉得这个方法比较好,注意当searchBar为空时preload tableview会再次消失。

      UISearchBarDelegate

      func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
          if searchText.isEmpty {
              dispatch_async(dispatch_get_main_queue()) {
                  self.searchController.searchResultsController?.view.hidden = false
              }
          }
      }
      
      func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
          dispatch_async(dispatch_get_main_queue()) {
              self.searchController.searchResultsController?.view.hidden = false
          }
      }
      

      UISearchControllerDelegate

      func willPresentSearchController(searchController: UISearchController) {
          dispatch_async(dispatch_get_main_queue()) {
              self.searchController.searchResultsController?.view.hidden = false
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2017-05-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多