UISearchController使用指南(Swift)

2016.07.03


引言

拖延了大半年最終還是決定老老實實走上寫blog的不歸路,正好最近在用swift重構項目中的搜索頁面,使用了UISearchController(iOS 8.0 & later),在使用過程中發現一些需要注意的地方,且感覺現在網上對UISearchController使用的介紹普遍不清晰或者過于簡單,遂決定拿它開刀,作為人生第一篇blog的主角。
本文盡量從工程實際使用價值的角度來介紹UISearchController,且提供一份示例項目代碼,歡迎留言討論。


概述

首先需要說明的是,UISearchController的使用場景有一定限制,概括來說,目前只有以下兩個場景下在工程使用中的可實現性得到了驗證,其他使用場景基本都存在專場動畫等方面的bug,如果你知道還有其他的實現場景,歡迎留言。

1.在UITableView的tableHeaderView中使用,實現類似微信首頁搜索的場景

ForTableHeaderView.gif

2.在NavigationBar的titleView上使用,實現類似淘寶首頁搜索的場景,這種場景可以做適當的衍生,實現navigationBarItem來觸發搜索界面,但歸根結底還是基于此種場景,故不再拿出單獨討論

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容