【iOS】UISearchBarで検索機能を実装する

目標

SearchBarに入力した文字列検索の結果をTableViewに表示する

検索機能を実装前のTableView

配列arrayの中身をTableViewで表示しているサンプルを活用して説明するよ。このViewContollerに検索機能を実装していくよ。

import UIKit  

class MainViewController: UIViewController {  
    @IBOutlet weak var tableView: UITableView!  

    private var array = [  
        "リンゴ",  
        "ゴリラ",  
        "Orange",  
        "桃",  
    ]  

    override func viewDidLoad() {  
        super.viewDidLoad()  
        // Do any additional setup after loading the view  

    }  
}  

// Mark: TableViewDelegate,DataSource  
extension MainViewController: UITableViewDelegate, UITableViewDataSource {  
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {  
        return array.count  
    }  

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {  
        let cell = UITableViewCell.init(style: .default, reuseIdentifier: "Cell")  
        cell.textLabel?.text  = array[indexPath.row]  
        return cell  
    }  
}  

手順解説

やり方としては大きく分けて次の二通りがあるよ

  • UISearchControllerにsearchResultsControllerをセットして実装する方法(画面遷移あり)
  • SearchBarのDelegateメソッドとTableViewのreloadDataを使って実装する

前者の方は工数がかかるかつ説明が大変そうなので後者のやり方を説明するよ。まずは大まかな流れを示すよ

  1. SearchBarの設置・Outlet接続
  2. SearchBarDelegateのプロトコル拡張
  3. DelegateメソッドでSeachBarに入力された文字列を取得する
  4. arrayの要素のうち3で取得した文字列にマッチした要素を先頭に並び替える

手順1. SearchBarの設置

  • StoryboardにSearchBarを設置
  • Outlet接続

詳しい解説は割愛しますが、特にseachbarのdelegateの設定を忘れないように!↓

手順2. ViewControllerのプロトコル拡張

// Mark: UISearchBarDelegate  
extension MainViewController: UISearchBarDelegate { }  

UISearchBarDelegateの拡張を行います

手順3. DelegateメソッドでSeachBarに入力された文字列を取得する

UISearchBarに入力した文字を確定したタイミングで呼び出されるメソッドsearchBarSearchButtonClickedを活用するよ

func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { }  

文字列の取得

SearchBarに入力された文字列はsearchBar.textで取得できるよ。オプショナル型での取得となるのでguard let等を使ってランラップするとよいよ。

func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {  
        guard let searchText = searchBar.text else {  
            return  
        }  
        print(searchText)  //SeachBarに入力された文字列が出力されるはず  
}  

手順4. 検索処理の実装

文字列の取得できたら後は検索処理のためのメソッドを定義し、呼び出せば良いだけだよ。今回はマッチする文字列を先頭に持ってくるのみに留めるよ。ポイントは2つ

  • SearchBarの文字列情報を渡す引数を用意する
  • tableView.reloadDataを忘れない(忘れると結果が反映されない)
private func search(_ text: String) {  
    var newArray: [String] = []  
    array.forEach({  
        if $0.contains(text) {  
            newArray.insert($0, at: 0)    
        } else {  
            newArray.append($0)  
        }  
    })  
    array = newArray  //新しい配列を代入  
    tableView.reloadData()  //反映させる  
}  

・最終的なサンプルコード

検索処理のメソッドが定義できたら、引数に渡しつつ呼び出すだけ

//MARK-: UISearchBarDelegate  
extension MainViewController: UISearchBarDelegate {  
    func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {  
        guard let searchText = searchBar.text else {  
            return  
        }  
        search(searchText)  
    }  

    private func search(_ text: String) {  
        var newArray: [String] = []  
        array.forEach({  
            if $0.contains(text) {  
                newArray.insert($0, at: 0)  
            } else {  
                newArray.append($0)  
            }  
        })  
        array = newArray  
        tableView.reloadData()  
    }  
}  

まとめ

結局はプロトコルを拡張して対応したDelegateメソッドを使ってあーだーこーだするだけだね。

  • SearchBarの文字列はsearchBar.textで取得できる
  • searchBarSearchButtonClickedはSearchBarの入力が確定されたタイミングで呼び出される
  • 最後にreloadDataを忘れない

補足: インクリメンタルサーチとは??

リアルタイムで検索結果が表示されるやつ

実装の方法は二種類あります

  1. textDidChangeを使う方法
  2. RxSwiftを使う

方法1. textDidChangeを活用する

今回使用するDelegateメソッドはtextDidChange。このメソッドはUISearchBarのDelegateメソッドで、SearchBarに文字が入力されるたびに呼び出されるメソッドだよ。searchBarSearchButtonClickedの代わりにこちらを使うとインクリメンタルサーチっぽくなるよ。

方法2. RxSwiftを使う

リアクティブプログラミングという手法で実装する方法です。RxSwiftというライブラリをインポートする必要があります。RxSwiftについては、別の記事に譲ることにします

最後までご覧いただきありがとうございました

こっちは真面目に作ってます。笑

サクっとプログラミング

iOSアプリ開発のあれこれがまとまるwebサイト