UISearchController使用指南(Swift)

2016.07.03


引言

拖延了大半年最终还是决定老老实实走上写blog的不归路,正好最近在用swift重构项目中的搜索页面,使用了UISearchController(iOS 8.0 & later),在使用过程中发现一些需要注意的地方,且感觉现在网上对UISearchController使用的介绍普遍不清晰或者过于简单,遂决定拿它开刀,作为人生第一篇blog的主角。
本文尽量从工程实际使用价值的角度来介绍UISearchController,且提供一份示例项目代码,欢迎留言讨论。


概述

首先需要说明的是,UISearchController的使用场景有一定限制,概括来说,目前只有以下两个场景下在工程使用中的可实现性得到了验证,其他使用场景基本都存在专场动画等方面的bug,如果你知道还有其他的实现场景,欢迎留言。

1.在UITableView的tableHeaderView中使用,实现类似微信首页搜索的场景

UISearchController使用指南(Swift)_第1张图片
ForTableHeaderView.gif

2.在NavigationBar的titleView上使用,实现类似淘宝首页搜索的场景,这种场景可以做适当的衍生,实现navigationBarItem来触发搜索界面,但归根结底还是基于此种场景,故不再拿出单独讨论

UISearchController使用指南(Swift)_第2张图片
ForNavigationBar.gif

基本设置

个人感觉UISearchController在工程中最大的意义应该在于可以轻松完成MVC解耦,将一个相对复杂的搜索Scene解耦成一个主MVC+一个子MVC。子MVC可以专注实现进入搜索状态时响应逻辑和页面展示等工作,而只需要在创建UISearchController时将子MVC的Controller设置为searchResultsController即可完成关联。而对于简单的搜索场景,如果只想在同一个MVC中完成搜索功能,只需将searchResultsController参数传入nil,并将UISearchController.searchResultsUpdater代理设置为当前MVC。

注意:


使用UISearchController时当前UIViewController有一个很重要的属性:definesPresentationContext,对应用场景一,应设置为false,防止出现细微的动画异常(真的很细微,不仔细看看不出来);对场景二,则必须设置为true,但是在当前页面willDisappear时,应将其设置回默认的false状态,否则可能对其他页面产生异常


以下基本设置按实际需求调整:

searchController = UISearchController(searchResultsController: searchResultsVC)

searchController.searchBar.frame = CGRectMake(0, 0, view.bounds.width, 44)

searchController.hidesNavigationBarDuringPresentation = true
searchController.dimsBackgroundDuringPresentation = true

searchController.searchResultsUpdater = searchResultsVC
searchController.delegate = self
searchController.searchBar.delegate = self

在这里介绍两个坑


一号坑:

searchBar.tintColor会同时改变光标的颜色,所以,如果当你在期望改变按钮颜色为白色时,光标就看不到了
解决方案:
单独设置searchBar的按钮颜色,这里因为当年swift没有支持可变参数函数,所以在iOS8时代没有对应的方法,需要用OC封装一下然后swift调用OC

if #available(iOS 9.0, *) {
    //此方法仅对9.0之后版本生效
    UIBarButtonItem.appearanceWhenContainedInInstancesOfClasses([UISearchBar.self]).tintColor = UIColor.whiteColor()
} else {
    //对9.0之前版本需桥接OC版对UIBarButtonItem的扩展
    UIBarButtonItem.my_appearanceWhenContainedIn(UISearchBar.self).tintColor = UIColor.whiteColor()
}
二号坑:

searBar默认控制在输入为空时键盘上搜索按钮不可点击,但是在向searchBar中粘贴字符串或者代码控制直接像searchBar.text赋值,键盘上的搜索按钮会依然处于失效状态,此bug疑似由UISearchController内部机制引起
解决方案:
A.关闭searBar输入为空时自动将搜索按钮置失效,但需要根据需求自己控制输入为空时是否允许触发搜索

searchController.searchBar.enablesReturnKeyAutomatically = false

B.在向searchBar中粘贴字符串或者代码控制直接向searchBar.text赋值时,对searchBar先resignFirstResponder再becomeFirstResponder
通过代码控制直接向searchBar.text赋值时此方案已得到验证,如何捕获粘贴字符串动作本人目前未能实现,故尚未验证,但是从前者的表现来看应该是可以的


代理实现

需要实现
1.UISearchBarDelegate
实现对键盘点击搜索等动作的响应

//MARK: UISearchBarDelegate
extension SearchControllerForTableHeaderViewController: UISearchBarDelegate {
    func searchBarSearchButtonClicked(searchBar: UISearchBar) {
        //点击键盘上的搜索按钮时执行此代理,可按实际需求进行处理
        print("didClickSearchBuuton")
    }
}

2.UISearchControllerDelegate
控制在进入/离开搜索状态时需要调整的设置和UI等

//MARK: UISearchControllerDelegate
extension SearchControllerForTableHeaderViewController: UISearchControllerDelegate {
    func willPresentSearchController(searchController: UISearchController) {
        //若需要在无输入时亦展示searchResultsController.view,需执行此句,必须在主线程中执行
        dispatch_async(dispatch_get_main_queue()) { () -> Void in
            searchController.searchResultsController!.view.hidden = false;
        }
    }
    
    func didPresentSearchController(searchController: UISearchController) {
        //对于由代码主动发起的searchController进入active状态,需在此设置        
        searchController.searchBar.becomeFirstResponder()
    }
}

3.UISearchResultsUpdating//根据searchResultsController是否为nil决定此代理由子MVC实现还是主MVC实现

//MARK: UISearchResultsUpdating
extension SearchResultsController: UISearchResultsUpdating {
    func updateSearchResultsForSearchController(searchController: UISearchController) {
        if self.searchController == nil {
            self.searchController = searchController
        }
        guard searchController.searchBar.text ?? "" != "" else {
            return
        }
        searchKeywords(searchController.searchBar.text!)
    }
}

示例项目传送门

最后附上示例项目传送门
https://github.com/LvJianting/UISearchControllerExample.git

你可能感兴趣的:(UISearchController使用指南(Swift))