質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.04%

navigationControllerとsearchControllerについて

受付中

回答 0

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 649

noblehorse

score 4

 前提・実現したいこと

ナビゲーションバーに検索バーを表示させ、検索するとスクロール可能なtableViewに検索結果を表示させることができ、スクロール時は検索バーが隠れるというよくある機能を実装したいと思っています。
例としては設定アプリのデザインを見てもらうとわかりやすいかもしれません。
これだけの条件での実装は自力で達成することができました。

ですが今回の開発ではナビゲーションバーのデザインとしてタイトルは必要なく、searchBarをナビゲーションバー内で表示させたいと思っています。

なので統合という形ではなく、基本的なNavigationBarの範囲内にsearchBarを埋め込むという形がもっとも理想的であると考えました。

そのためnavigationBarのnavigationitem.titleViewにsearchController.searchBarを入れて実装することにしたところ、シミュレーターでほとんどは正常に作動したのですが、検索結果のスクロール時にサーチバーが隠れるという機能が作動しませんでした。

上記の設定アプリを土台として作成していたため

self.navigationItem.hidesSearchBarWhenScrolling = true


というコードで作動すると思ったのですがうまくいきませんでした。

上記のコードはnavigationitem.titleViewに入れたsearchBarには使えないのでしょうか?または上記のコードを邪魔してしまってるコードが書かれてしまっているのでしょうか?お教え願います。

また、この方法で作ること自体が非常に困難であるということでしたら、他の方法をぜひお教え願います。

 該当のソースコード

import UIKit

class ViewController: UIViewController, UISearchBarDelegate,  UITableViewDelegate, UITableViewDataSource, UISearchResultsUpdating {





    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var scrollView: UIScrollView!

    var searchController: UISearchController!

    let search:[String] = [

        "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"

    ]
    var searchResults:[String] = []





    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.



        searchBarCustom()

    }


    func searchBarCustom(){

        self.searchController = UISearchController(searchResultsController: nil)
        self.searchController.searchResultsUpdater = self
        self.searchController.obscuresBackgroundDuringPresentation = false
        self.searchController.hidesNavigationBarDuringPresentation = false


        //NavigationBarにSearchBarを追加
        //searchBarを追加しただけなのでこれだけのコードでは検索バーのタップ時にキャンセルボタンが表示されない!なので①
        searchController.searchBar.delegate = self
        searchController.searchBar.placeholder = "search"
        searchController.searchBar.setValue("キャンセル", forKey: "_cancelButtonText")
        self.definesPresentationContext = true




        //初期画面では常にsearchBarを表示させておく
        //下スクロール時はsearchBarを隠し、上スクロール時にsearchBarを出す
        if #available(iOS 11.0, *){

        self.navigationItem.titleView = self.searchController.searchBar

            // trueだとスクロールした時にSearchBarを隠す(デフォルトはtrue)
            // falseだとスクロール位置に関係なく常にSearchBarが表示される
            self.navigationItem.hidesSearchBarWhenScrolling = true

        } else {
            // iOS 11未満は別処理が必要
            navigationItem.titleView = searchController.searchBar
        }


    }







        // 検索ボタンが押された時に呼ばれる
    private func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {

            self.view.endEditing(true)
            searchController.isActive = true
            self.searchResults = search.filter{
                // 大文字と小文字を区別せずに検索
                $0.lowercased().contains(searchController.searchBar.text!.lowercased())
            }
            self.tableView.reloadData()
        }


        // テキストフィールド入力開始前に呼ばれる(キャンセルボタン表示)
    private func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool {

            searchController.isActive = true  //①ここでキャンセルボタンの追加が必要!
        return true
    }

    // キャンセルボタンが押された時に呼ばれる
    private func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        searchController.isActive = false
         self.view.endEditing(true)
        searchController.searchBar.text = ""
         self.tableView.reloadData()
    }


    //データの個数を返すメソッド
    func tableView(_ tableView: UITableView, numberOfRowsInSection: Int) -> Int {
        if searchController.searchBar.text != "" {
            return searchResults.count
        } else {
            return search.count
        }
    }
    //tableViewCellの作成&検索結果表示

    internal func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath as IndexPath)
        if searchController.searchBar.text != "" {
            cell.textLabel!.text = "\(searchResults[indexPath.row])"
        } else {
            cell.textLabel!.text = "\(search[indexPath.row])"
        }

        return cell
    }



    func updateSearchResults(for searchController: UISearchController) {

    }




    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }




}

 試したこと

UIsearchControllerではなくUIsearchBarでの開発を試みましたが、 hidesSearchBarWhenScrollingのようなものを発見することができず、諦めてしまいました。
作動しなかったコードを邪魔してしまっているコードがないか探しましたが、私自身の力では探し出すことができませんでした。

 補足情報(FW/ツールのバージョンなど)

Xcode Version10.0
swift 4.2

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.04%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る