【SwiftUI】リスト(一覧表示)に検索ボックスをつける方法

本記事では、SwiftUIで実現できるリスト表示に検索ボックスをつけて、リストの中から指定した文字列を含むレコードを絞り込む方法を解説していきます。

リスト表示の方法や、ラベル/画像を入れる、リストを複数のセクションに分割する、タイトルをつけるなどのやり方については以下の記事で詳細に解説していますのでぜひご覧ください。

リスト検索の全体像

今回ご紹介するリスト検索のソースと表示内容は以下になります。

struct ContentView: View {
    var lists = ["群馬県","栃木県","茨城県","埼玉県","千葉県","東京都","神奈川県"]
    @State private var searchText = ""
    var body: some View {
        NavigationView{
            List{
                ForEach(searchResults, id: \.self){ name in
                    Text(name)
                }
            }.searchable(text: $searchText, prompt: "都道府県の検索")
                .keyboardType(.default)
                .navigationTitle("都道府県")
        }
    }
    
    var searchResults: [String]{
        if searchText.isEmpty{
            return lists
        }else{
            return lists.filter{$0.contains(searchText)}
        }
    }
}

実行結果

リストと検索ボックスが表示されていることが確認できたかと思います。

ここからは順を追って実際に検索ができているスクリーンショットも添えながらソースコードの解説をしていきます。

配列とリストを作成する

まずは配列とリスト表示の部分を作成します。この工程は別記事で紹介しているため簡潔にいたします。

まず、配列を作成して、そこにString型のデータを格納しています。その後、ForEach文を使用して配列の中身をリスト表示し、navigationTitle()によってタイトルをつけていることが確認できます。

struct ContentView: View {
    var lists = ["群馬県","栃木県","茨城県","埼玉県","千葉県","東京都","神奈川県"]
    var body: some View {
        NavigationView{
            List{
                ForEach(lists, id: \.self){ name in
                    Text(name)
                }
            }.navigationTitle("都道府県")
        }
    }
}

実行結果

検索ボックスをつける

用意したリストに対して検索ボックスをつけていきます。検索ボックスをつける方法は、List{}に.searchable()をつけます。

searchableの括弧内では、textパラメータには検索ボックスに入力された値を取得するための変数を格納することができ、promptを設定した場合にはプレースホルダーとして表示する文字列を設定することができます。

searchable()をつけることで検索ボックスを付与した後は、検索ボックスに入力された値を取得する必要があるため、取得用の変数も@Stateで用意してあげます。

keyboardType(.default)では、検索ボックスをクリックした時に表示されるキーボードの種類を設定することができ、.defaultでiphoneのデフォルトのキーボードが表示されるようになります。

struct ContentView: View {
    var lists = ["群馬県","栃木県","茨城県","埼玉県","千葉県","東京都","神奈川県"]
    @State private var searchText = ""
    var body: some View {
        NavigationView{
            List{
                ForEach(lists, id: \.self){ name in
                    Text(name)
                }
            }.searchable(text: $searchText, prompt: "都道府県の検索")
                .keyboardType(.default)
                .navigationTitle("都道府県")
        }
    }
}

実行結果

検索結果用の配列を作成する

先ほど作成した検索ボックスを利用して、リストの中から実際に検索ボックスに入力された文字列で検索を行う方法です。

まず、seachResultsという検索後のlists内の一覧を格納する変数を用意します。searchResultsには、検索ボックスに入力された値であるsearchTextの中身が、空であるかを判定するためにif文の中で searchText.isEmptyを確認します。

空だった場合には、何も検索されていないため、変数listの中身をsearchResultsに代入します。

値が入っている場合にはelseの中で、lists.filter{$0.contains(searchText)}を使用して変数listの中からsearchTextの文字列を含む値のみを取得してsearchResultsの中に代入されます。

var searchResults: [String]{
        if searchText.isEmpty{
            return lists
        }else{
            return lists.filter{$0.contains(searchText)}
        }
    }

最後はForEachで表示しているリストをlistからsearchResultsに変更することで、検索されていない時には全件を、検索された場合には検索対象のみを表示するリストを作成することができました。

最後に

本記事では、作成したリストの中から任意の列を検索する方法を解説してきました。他の記事で、リストの基本的な使い方やクラス、インスタンンスの使用方法などSwiftUIに関する記事を書いていますので、ぜひそちらもご覧ください。