swift

【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で取得した文字列にマッチした要素を先頭に並び替える

①SearchBarを設置する

UIKitではお決まりの作業ですが次の2つを行います。

  • StoryboardにSearchBarを設置する
  • Outlet接続を行う

特にseachbarのdelegateの設定を忘れないようにしてください。 enter image description here

②ViewControllerのプロトコル拡張

// Mark: UISearchBarDelegate
extension MainViewController: UISearchBarDelegate { }

UISearchBarDelegateの拡張を行います。これによりUIViewControllerでもUISearchBarのメソッドをよびせるようになります。

③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に入力された文字列が出力されるはず
}

④検索処理の実装

文字列の取得できたら後は検索処理のためのメソッドを定義し、searchBarSearchButtonClickedのどこかで呼び出せば良いです。今回は配列arrayの順番を操作してマッチする文字列を先頭に持ってくるのみ留めます。メソッドの実装に当たってポイントは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()  //反映させる
}

最終的なサンプルコード

検索処理のメソッドが定義できたら、searchBarに渡された文字列を引数に渡しつつsearchを呼び出します

//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()
    }
}

まとめ

最後に内容をまとめておきます。

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

補足: 「インクリメンタルサーチ」について

文字を入力中、リアルタイムで検索結果が反映されるのがインクリメンタルサーチです。

実装

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

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

方法2. RxSwiftを使う

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

読んでいただきありがとうございます!!

記事として取り上げたトピックを体系化してまとめた内容を電子書籍として販売しています。購入していただくことで執筆の応援ができます。詳細はこちらから