UISearchController: show results even when search bar is empty

前端 未结 14 2176
独厮守ぢ
独厮守ぢ 2020-12-23 13:27

As I understand, the default behaviour of UISearchController is:

  1. On tapping search bar, background is dimmed and \'cancel\' button is shown.
相关标签:
14条回答
  • 2020-12-23 13:42

    I spent a lot of time with this, and ultimately the solution I went with is like @malhals's, but the amount of code is significantly reduced by using facebook's KVOController: https://github.com/facebook/KVOController . Another advantage here is that if your searchResultsController is a UINavigationController then you don't need to subclass it just to add @malhal's code.

    // always show searchResultsController, even if text is empty
    [self.KVOController observe:self.searchController.searchResultsController.view keyPath:@"hidden" options:NSKeyValueObservingOptionNew block:^(id observer, UIView* view, NSDictionary *change) {
        if ([change[NSKeyValueChangeNewKey] boolValue] == YES) {
            view.hidden = NO;
        }
    }];
    self.searchController.dimsBackgroundDuringPresentation = NO;
    
    0 讨论(0)
  • 2020-12-23 13:43

    Updated for iOS 13

    From iOS13, we got system API support for this behaviour. You can set the property showsSearchResultsController = true

    WWDC screenshot

    For iOS 12 and below

    I am recently working on UISearchController. I want to show search history in searchResultsController when search bar is empty. So searchResultsController needs to show up whenever UISearchController gets presented.

    Here, I use another solution to make the searchResultsController always visible by overriding the hidden property in a custom view.

    for example, my searchResultsController is a UITableViewController. I create a VisibleTableView as a subclass of UITableView, and then change the UITableView custom class of searchResultsController to VisibleTableView in xib or storyboard. This way, my searchResultsController will never be hidden by UISearchController.

    The good things here:

    1. Easier to implement than KVO.

    2. No delay to show searchResultsController. Flipping the hidden flag in "updateSearchResults" delegate method works, but there is a delay to show the searchResultsController.

    3. It does't reset the hidden flag, so there is no UI gap/jumping between hidden and visible.

    Swift 3 sample code:

    class VisibleTableView: UITableView {
    override var isHidden: Bool {
        get {
            return false
        }
        set {
            // ignoring any settings
        }
    }
    }
    
    0 讨论(0)
  • 2020-12-23 13:43

    The easiest way is to use ReactiveCocoa with this extension https://github.com/ColinEberhardt/ReactiveTwitterSearch/blob/master/ReactiveTwitterSearch/Util/UIKitExtensions.swift

            presentViewController(sc, animated: true, completion: {
                sc.searchResultsController?.view.rac_hidden.modify({ value -> Bool in
                    return false
                })
            } )
    

    where sc is your UISearchController

    0 讨论(0)
  • 2020-12-23 13:44

    Swift 3 Version:

    If your searchResultController is not nil and you are using a separate table view controller to show the search results, then you can make that table view controller conform to UISearchResultUpdating and in the updateSearchResults function, you can simply unhide the view.

    func updateSearchResults(for searchController: UISearchController) {
        view.hidden = false
    }
    

    Swift 4 Version:

    func updateSearchResults(for searchController: UISearchController) {
        view.isHidden = false
    }
    
    0 讨论(0)
  • 2020-12-23 13:46

    If your searchBar is active but has no text, the underlying tableView results are shown. That's the built-in behavior, and the reason why searchResultsController is hidden for that state.

    To change the behavior when search is active but not filtering, you're going to have to show the searchResultsController when it is normally still hidden.

    There may be a good way to accomplish this via <UISearchResultsUpdating> and updateSearchResultsForSearchController:. If you can solve it via the protocol, that's the preferred way to go.

    If that doesn't help, you're left with hacking the built-in behavior. I wouldn't recommend or rely on it, and it's going to be fragile, but here's an answer if you choose that option:

    1. Make sure your tableViewController conforms to <UISearchControllerDelegate>, and add

      self.searchController.delegate = self;

    2. Implement willPresentSearchController:

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

      This makes the searchResultsController visible after its UISearchController set it to hidden.

    3. Implement didPresentSearchController:

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

    For a better way to work around the built-in behavior, see malhal's answer.

    0 讨论(0)
  • 2020-12-23 13:52

    The Swift 2.3 version of @malhal's approach:

    class SearchResultsViewController : UIViewController {
        var context = 0
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Add observer
            view.addObserver(self, forKeyPath: "hidden", options: [ .New, .Old ], context: &context)
        }
    
        deinit {
            view.removeObserver(self, forKeyPath: "hidden")
        }
    
        override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
            if context == &self.context {
                if change?[NSKeyValueChangeNewKey] as? Bool == true {
                    view.hidden = false
                }
            } else {
                super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题