この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
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からはこのプロパティを使っていきましょう。