栃木県のJavaエンジニア、WEBプログラマーのためのサイト

2015.10.20[Swift] UISearchDisplayControllerからUISearchControllerに書き換える

UISearchController

UISearchDisplayController が iOS8 から deprecated なので UISearchController に書き換える

修正点

  • Storyboard に UISearchDisplayController (Search Bar and Search Bar Search Display Controller) を貼り付けていたのを、コードで UISearchController を生成するように変更
  • 絞り込み処理を記述するメソッドが searchDisplayController から updateSearchResultsForSearchController に変更
  • 検索中の判定は active プロパティ

修正前のUISearchDisplayControllerを用いたコード(抜粋)

// UISearchDisplayControllerのインスタンスsearchDisplayControllerはStoryboardで生成
class TableViewController: UITableViewController {
    /// 表示データ
    var items: [Item] = []
    var filteredItems: [Item] = []

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return (tableView == searchDisplayController?.searchResultsTableView) ? filteredItems.count : items.count
    }
}

extension TableViewController: UISearchDisplayDelegate {
    func searchDisplayController(controller: UISearchDisplayController, shouldReloadTableForSearchString searchString: String?) -> Bool {
        let options: NSStringCompareOptions = [NSStringCompareOptions.CaseInsensitiveSearch, NSStringCompareOptions.WidthInsensitiveSearch]

        filteredItems = items.filter() { item in
            let string = "\(item.name) \(item.type1) \(item.type2) \(item.type3)"
            return string.rangeOfString(searchString!, options: options) != nil
        }
        
        return true
    }
}

修正後のUISearchControllerを用いたコード(抜粋)

class TableViewController: UITableViewController {
    /// サーチコントローラ
    var searchController = UISearchController(searchResultsController: nil)
    
    /// 表示データ
    var items: [Item] = []
    var filteredItems: [Item] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // サーチコントローラ設定
        searchController.searchResultsUpdater = self
        searchController.hidesNavigationBarDuringPresentation = false
        searchController.dimsBackgroundDuringPresentation = false
        searchController.searchBar.searchBarStyle = UISearchBarStyle.Prominent
        searchController.searchBar.sizeToFit()
        tableView.tableHeaderView = searchController.searchBar
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return searchController.active ? filteredItems.count : items.count
    }
}

extension TableViewController: UISearchResultsUpdating {
    func updateSearchResultsForSearchController(searchController: UISearchController) {
        let options: NSStringCompareOptions = [NSStringCompareOptions.CaseInsensitiveSearch, NSStringCompareOptions.WidthInsensitiveSearch]
        let text = searchController.searchBar.text!
        
        filteredItems = items.filter() { item in
            let string = "\(item.name) \(item.type1) \(item.type2) \(item.type3)"
            return string.rangeOfString(text, options: options) != nil
        }
        tableView.reloadData()
    }
}

Storyboard側に記述していた部分が、コード側に移った分増えただけでほぼ同じ感じです

参考