前提・実現したいこと
ナビゲーションバーに検索バーを表示させ、検索するとスクロール可能なtableViewに検索結果を表示させることができ、スクロール時は検索バーが隠れるというよくある機能を実装したいと思っています。
例としては設定アプリのデザインを見てもらうとわかりやすいかもしれません。
これだけの条件での実装は自力で達成することができました。
ですが今回の開発ではナビゲーションバーのデザインとしてタイトルは必要なく、searchBarをナビゲーションバー内で表示させたいと思っています。
なので統合という形ではなく、基本的なNavigationBarの範囲内にsearchBarを埋め込むという形がもっとも理想的であると考えました。
そのためnavigationBarのnavigationitem.titleViewにsearchController.searchBarを入れて実装することにしたところ、シミュレーターでほとんどは正常に作動したのですが、検索結果のスクロール時にサーチバーが隠れるという機能が作動しませんでした。
上記の設定アプリを土台として作成していたため
self.navigationItem.hidesSearchBarWhenScrolling = true
というコードで作動すると思ったのですがうまくいきませんでした。
上記のコードはnavigationitem.titleViewに入れたsearchBarには使えないのでしょうか?または上記のコードを邪魔してしまってるコードが書かれてしまっているのでしょうか?お教え願います。
また、この方法で作ること自体が非常に困難であるということでしたら、他の方法をぜひお教え願います。
該当のソースコード
swift
1 2import UIKit 3 4class ViewController: UIViewController, UISearchBarDelegate, UITableViewDelegate, UITableViewDataSource, UISearchResultsUpdating { 5 6 7 8 9 10 @IBOutlet weak var tableView: UITableView! 11 @IBOutlet weak var scrollView: UIScrollView! 12 13 var searchController: UISearchController! 14 15 let search:[String] = [ 16 17 "row1", "row2", "row3", "row4", "row5", 18 "row6", "row7", "row8", "row9", "row10", 19 "row11", "row12", "row13", "row14", "row15", 20 "row16", "row17", "row18", "row19", "row20", 21 "row21", "row22", "row23", "row24", "row25", 22 "row26", "row27", "row28", "row29", "row30" 23 24 ] 25 var searchResults:[String] = [] 26 27 28 29 30 31 override func viewDidLoad() { 32 super.viewDidLoad() 33 // Do any additional setup after loading the view, typically from a nib. 34 35 36 37 searchBarCustom() 38 39 } 40 41 42 func searchBarCustom(){ 43 44 self.searchController = UISearchController(searchResultsController: nil) 45 self.searchController.searchResultsUpdater = self 46 self.searchController.obscuresBackgroundDuringPresentation = false 47 self.searchController.hidesNavigationBarDuringPresentation = false 48 49 50 //NavigationBarにSearchBarを追加 51 //searchBarを追加しただけなのでこれだけのコードでは検索バーのタップ時にキャンセルボタンが表示されない!なので① 52 searchController.searchBar.delegate = self 53 searchController.searchBar.placeholder = "search" 54 searchController.searchBar.setValue("キャンセル", forKey: "_cancelButtonText") 55 self.definesPresentationContext = true 56 57 58 59 60 //初期画面では常にsearchBarを表示させておく 61 //下スクロール時はsearchBarを隠し、上スクロール時にsearchBarを出す 62 if #available(iOS 11.0, *){ 63 64 self.navigationItem.titleView = self.searchController.searchBar 65 66 // trueだとスクロールした時にSearchBarを隠す(デフォルトはtrue) 67 // falseだとスクロール位置に関係なく常にSearchBarが表示される 68 self.navigationItem.hidesSearchBarWhenScrolling = true 69 70 } else { 71 // iOS 11未満は別処理が必要 72 navigationItem.titleView = searchController.searchBar 73 } 74 75 76 } 77 78 79 80 81 82 83 84 // 検索ボタンが押された時に呼ばれる 85 private func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { 86 87 self.view.endEditing(true) 88 searchController.isActive = true 89 self.searchResults = search.filter{ 90 // 大文字と小文字を区別せずに検索 91 $0.lowercased().contains(searchController.searchBar.text!.lowercased()) 92 } 93 self.tableView.reloadData() 94 } 95 96 97 // テキストフィールド入力開始前に呼ばれる(キャンセルボタン表示) 98 private func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool { 99 100 searchController.isActive = true //①ここでキャンセルボタンの追加が必要! 101 return true 102 } 103 104 // キャンセルボタンが押された時に呼ばれる 105 private func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { 106 searchController.isActive = false 107 self.view.endEditing(true) 108 searchController.searchBar.text = "" 109 self.tableView.reloadData() 110 } 111 112 113 //データの個数を返すメソッド 114 func tableView(_ tableView: UITableView, numberOfRowsInSection: Int) -> Int { 115 if searchController.searchBar.text != "" { 116 return searchResults.count 117 } else { 118 return search.count 119 } 120 } 121 //tableViewCellの作成&検索結果表示 122 123 internal func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 124 let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath as IndexPath) 125 if searchController.searchBar.text != "" { 126 cell.textLabel!.text = "(searchResults[indexPath.row])" 127 } else { 128 cell.textLabel!.text = "(search[indexPath.row])" 129 } 130 131 return cell 132 } 133 134 135 136 func updateSearchResults(for searchController: UISearchController) { 137 138 } 139 140 141 142 143 override func didReceiveMemoryWarning() { 144 super.didReceiveMemoryWarning() 145 // Dispose of any resources that can be recreated. 146 } 147 148 149 150 151}
試したこと
UIsearchControllerではなくUIsearchBarでの開発を試みましたが、 hidesSearchBarWhenScrollingのようなものを発見することができず、諦めてしまいました。
作動しなかったコードを邪魔してしまっているコードがないか探しましたが、私自身の力では探し出すことができませんでした。
補足情報(FW/ツールのバージョンなど)
Xcode Version10.0
swift 4.2
あなたの回答
tips
プレビュー