[iOS 11] iOS 11で追加されたUINavigationItemのsearchControllerプロパティを使ってSearchBarをナビゲーションインターフェースに統合する
iOS 11で追加されたUINavigationItemのsearchControllerプロパティ
iOS 11でUINavigationItemに追加されたsearchController
プロパティを使用すると簡単にUINavigationBarにSearchBarを統合することができます。
ここで「統合」と表現したのは、「ナビゲーションバーに埋め込まれたように表示することができる」という意味です。
検証環境
本エントリは以下の環境で検証を行っています。
- macOS Sierra バージョン 10.12.6
- Xcode Version 9.0.1 (9A1004)
- Swift 4
- iPhone X シミュレーター iOS 11.0
こんな見た目になります
先にこのプロパティを使ってSearchBarを表示した結果を載せておきます。
ご覧のようにナビゲーションバーに埋め込まれる形でSearchBarが表示されます。
また、スクロール時にSearchBarが消えたり現れたりしています。
ソースコード(該当部分を抜粋)
以下が該当のプロパティを使っている部分のソースコードです。
UISearchController
を生成したらsearchController
プロパティにセットするだけです。簡単ですね。
hidesSearchBarWhenScrolling
もiOS 11から追加されたプロパティでスクロール時のSearchBarの表示を制御します。
注意点としてiOS 11から追加されたプロパティなので11未満の場合は別の処理が必要になります。
今回はtableHeaderViewにSearchBarをセットしています。
searchController = UISearchController(searchResultsController: nil) searchController.searchResultsUpdater = self searchController.obscuresBackgroundDuringPresentation = false navigationItem.title = "Sample data" if #available(iOS 11.0, *) { // UISearchControllerをUINavigationItemのsearchControllerプロパティにセットする。 navigationItem.searchController = searchController // trueだとスクロールした時にSearchBarを隠す(デフォルトはtrue) // falseだとスクロール位置に関係なく常にSearchBarが表示される navigationItem.hidesSearchBarWhenScrolling = true } else { // iOS 11未満は別処理が必要 tableView.tableHeaderView = searchController.searchBar }
ソースコード全体
ソースコード全体は以下です。
import UIKit class ViewController: UIViewController { @IBOutlet weak var tableView: UITableView! private var searchController: UISearchController! private let titles = [ "row1", "row2", "row3", "row4", "row5", "row6", "row7", "row8", "row9", "row10", "row11", "row12", "row13", "row14", "row15", "row16", "row17", "row18", "row19", "row20", "row21", "row22", "row23", "row24", "row25", "row26", "row27", "row28", "row29", "row30" ] private var filteredTitles = [String]() override func viewDidLoad() { super.viewDidLoad() setup() } // MARK: Private Methods private func setup() { searchController = UISearchController(searchResultsController: nil) searchController.searchResultsUpdater = self searchController.obscuresBackgroundDuringPresentation = false navigationItem.title = "Sample data" if #available(iOS 11.0, *) { // UISearchControllerをUINavigationItemのsearchControllerプロパティにセットする。 navigationItem.searchController = searchController // trueだとスクロールした時にSearchBarを隠す(デフォルトはtrue) // falseだとスクロール位置に関係なく常にSearchBarが表示される navigationItem.hidesSearchBarWhenScrolling = true } else { tableView.tableHeaderView = searchController.searchBar } tableView.dataSource = self tableView.delegate = self } } // MARK: - UISearchResultsUpdating extension ViewController: UISearchResultsUpdating { func updateSearchResults(for searchController: UISearchController) { // SearchBarに入力したテキストを使って表示データをフィルタリングする。 let text = searchController.searchBar.text ?? "" if text.isEmpty { filteredTitles = titles } else { filteredTitles = titles.filter { $0.contains(text) } } tableView.reloadData() } } // MARK: - UITableViewDataSource extension ViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { if searchController.isActive { return filteredTitles.count } else { return titles.count } } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) cell.textLabel?.text = searchController.isActive ? filteredTitles[indexPath.row] : titles[indexPath.row] return cell } } // MARK: - UITableViewDelegate extension ViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) } }
おわりに
iOS 11で追加されたUINavigationItemのsearchControllerプロパティをご紹介しました。
このプロパティはBuilding Apps for iPhone Xの中で、SearchBar部分のレイアウト崩れを修正する手段としても使われています。
iOS 11からはこのプロパティを使っていきましょう。