【iOS开发】UISearchController的使用

在使用app时,搜索一个列表的内容是非常常见的,例如苹果自带的联系人:

联系人.jpeg

我们可以使用UISearchController来实现这个功能。

UISearchController的属性

我们先来看看UISearchController有哪些属性:

// 初始化器:如果要在同一个控制器中显示搜索结果,searchResultsController参数传入nil (建议传入一个新的控制器,原因下面会讲到)
public init(searchResultsController: UIViewController?)

// 负责更新searchResultsController的内容
weak open var searchResultsUpdater: UISearchResultsUpdating?

// 是否激活
open var isActive: Bool

// 代理    
weak open var delegate: UISearchControllerDelegate?

// 显示的时候是否加上阴影效果,默认是true
open var dimsBackgroundDuringPresentation: Bool 

// 模糊背景效果,默认是true
open var obscuresBackgroundDuringPresentation: Bool

// 显示的时候是否隐藏导航栏,默认是true
open var hidesNavigationBarDuringPresentation: Bool

// 访问searchResultsController
open var searchResultsController: UIViewController? { get }

// 可以使用searchBar的代理来跟踪文本变化和按钮的事件
open var searchBar: UISearchBar { get }

初始化并设置相关属性

viewDidLoad初始化:

private func setupSearchController() { 
        //这个是另外创建的一个控制器,用来显示搜索结果
        searchResultController = SearchResultTableViewController(style: .plain) 
        searchController = UISearchController(searchResultsController: searchResultController)
        // 需要实现UISearchResultsUpdating这个协议,才能更新搜索结果
        searchController.searchResultsUpdater = self 
        searchController.delegate = self
        searchController.searchBar.placeholder = "搜索"
        
        tableView.tableHeaderView = searchController.searchBar
}

UISearchResultsUpdating协议

我们通过扩展来实现这个协议:

extension TableViewController: UISearchResultsUpdating {
    
    func updateSearchResults(for searchController: UISearchController) {
        searchResults = [] // 每次更新结果之前,把之前的搜索结果清零
        
        if let searchText = searchController.searchBar.text {
            for str in dataSource {
                if str.contains(searchText) {
                    searchResults.append(str)
                }
            }
        }
        
        searchResultController.dataSource = searchResults // 把搜索结果赋值给显示结果控制器的数据源
    }
}

UISearchControllerDelegate

我们通过扩展来实现这个代理,各个方法在何时调用,方法名很明显能看到,不再赘述:

extension TableViewController: UISearchControllerDelegate {
    
    func presentSearchController(_ searchController: UISearchController) {
        print("presentSearchController")
    }
    
    func willPresentSearchController(_ searchController: UISearchController) {
        print("willPresentSearchController")
    }
    
    func didPresentSearchController(_ searchController: UISearchController) {
        print("didPresentSearchController")
    }
    
    func willDismissSearchController(_ searchController: UISearchController) {
        print("willDismissSearchController")
    }
    
    func didDismissSearchController(_ searchController: UISearchController) {
        print("didDismissSearchController")
    }
}

显示结果的控制器

在数据源中使用didSet属性观察者,在被赋值后,刷新tableView

var dataSource: [String]! {
        didSet {
            tableView.reloadData()
        }
    }

另外,在numberOfRowsInSection方法中,要注意判断数据源是否为nil,因为搜索控制器被激活后,用户还没有输入搜索文字,这时数据源为nil

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        guard dataSource != nil else { return 0 }
        
        return dataSource.count
    }

为什么要在另外一个控制器显示搜索结果

如果直接使用同一个控制器显示结果,我们不能根据搜索文字的变化通过更改dimsBackgroundDuringPresentation属性来选择是否加上阴影效果。这样会影响我们点击显示搜索结果的cell。但是用另外一个控制器就没有问题。

Demo地址 >>

如果文中有错误,请指出!我们共同学习,共同进步。谢谢!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容