在搜索栏点击上显示 UISearchController 的 SearchResultsController

问题描述 投票:0回答:5

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

ios uisearchcontroller
5个回答
26
投票

当结果为空时,

UISearchController
viewController
仍然隐藏。这就是为什么我们必须使用
UISearchControllerDelegate
willPresentSearchController:

来解决问题

初始化后
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;
}

9
投票

我发现其他答案由于使用

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

5
投票

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
}

3
投票

我觉得这个方法比较好,小心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
    }
}

0
投票

Swfit 5 版本,带有简化代码

模块构建器

let resultViewController = YourResultViewController()
let searchBarController = UISearchController(searchResultsController: resultViewController)
searchBarController.searchBar.delegate = resultViewController as? UISearchBarDelegate
navigationItem.searchController = searchBarController

您的ResultViewController:UISearchBarDelegate

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    if searchText.isEmpty {
        DispatchQueue.main.async {
            self.view.isHidden = false
        }
    }
}

func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
    DispatchQueue.main.async {
        self.view.isHidden = false
    }
}
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.