Show UISearchController's SearchResultsController on SearchBar Tap

喜欢而已 提交于 2019-11-28 20:26:52

问题


I am using UISearchController not UISearchDisplayController, and I want to show SearchResultController on SearchBar Tap right away. Right now it's showing like this (when I tap on the search bar):


回答1:


When results are empty, UISearchController's viewController is still hidden. That's why we have to fiddle our way around using UISearchControllerDelegate's willPresentSearchController:

After initializing self.searchController make your ViewController conform to `UISearchControllerDelegate:

self.searchController.delegate = self;

Implement willPresentSearchController: in your ViewController:

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

The async dispatch is necessary, because otherwise it will be overridden by the internal behavior. You could go fancy here and use an animation to have the table view fade in.

Additionally, implement didPresentSearchController: for sanity:

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



回答2:


I found that the other answers had flickering due to using dispatch_async. They used this so that their changes would be applied after the internal behavior of the search controller had completed, but this leaves a couple frames where the internal behavior is applied before it is overridden. Using KVO allowed me to immediately override the internal behavior without any flickering.

I also found that the other answers did not keep the search results controller visible when a user tapped the ⓧ button to clear the contents of the search bar, which seems incorrect to me.

- (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;
}



回答3:


Chris Vasselli's answer is the cleanest way to implement this.

Here it is in 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:


I think this method is better, be careful when searchBar is empty then preload tableview will disappear again.

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
    }
}


来源:https://stackoverflow.com/questions/29196752/show-uisearchcontrollers-searchresultscontroller-on-searchbar-tap

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!