4
4

More than 1 year has passed since last update.

SwiftUIのsearchableモディファイアを使ってみる

Posted at

アプリで検索機能を実装するときによく使用するのがSearchBarですが、iOS15からSwiftUIに.searchableモディファイアが追加されたので使い方などを書いていこうと思います。

事前に

今回の記事で使用する検索フィールドを追加するViewです。
こちらのコードにsearchableモディファイアなどを追加していきます。

struct ContentView: View {
    
    let colors: [String] = ["Red", "Blue", "Yellow", "Purple", "Orange", "Green", "Pink", "White", "Gray", "Black"]
    
    var body: some View {
        NavigationView {
            List {
                ForEach(colors, id: \.self) { color in
                    Text(color)
                }
            }
            .navigationTitle("Colors")
        }
    }
}

searchableモディファイアのパラメータ

text
検索フィールドに表示、編集するテキスト

placement
検索フィールドの配置場所を設定する

実装

初めに検索フィールドに入力したテキストを保持するための@Stateを付与したプロパティを定義します。

@State private var text = ""

次にNavigationViewにsearchableモディファイアを追加します。

NavigationView {
    List {
        ForEach(colors, id: \.self) { color in
            Text(color)
        }
    }
    .navigationTitle("Colors")
}
.searchable(text: $text)

この状態で動作確認をしてみるとわかると思いますが、最初は検索フィールドが隠れており、スクロールしないと検索フィールドが表示されません。

常に表示されるようにしたい場合は以下のように変更します。

.searchable(text: $text, placement: .navigationBarDrawer(displayMode: .always))

これで常に検索フィールドが表示されるようになりましたが、NavigationViewのタイトルの初期状態がinlineになり、スクロールなどを行うとlargeTitleに戻るような動作になってしまうようです。初めからlargeTitle状態にする方法がわかりませんでした。。

Listに表示するデータを修正する

入力されているテキストが含まれているデータのみListに表示されるようにコードを追加・修正します。

var filteredColors: [String] {
    if text.isEmpty {
        return colors
    } else {
        return colors.filter { $0.lowercased().contains(text.lowercased()) }
    }
}
ForEach(filteredColors, id: \.self) { color in
    Text(color)
}

検索候補を表示する

searchableモディファイアでは、検索フィールドにテキストを入力しているときに検索候補を表示することができるsuggestions:パラメータがあります。
こちらはViewを返すようになっているので、以下のように実装することができます。

.searchable(text: $text, placement: .navigationBarDrawer(displayMode: .always)) {
    Text("Red").searchCompletion("Red")
    Text("Purple").searchCompletion("Purple")
    Text("Green").searchCompletion("Green")
}

検索候補をタップした際にsearchCompletion(_:)に指定した文字列が、編集中の検索フィールドのテキストを置き換えます。

onSubmitモディファイア

今回は使用しませんが、キーボードのリターンキーが押された時などに処理を実行させたい場合にonSubmitモディファイアを使用します。

.onSubmit(of: .search) {
    print("Submit")
}

アクションが呼ばれるタイミングは以下の通りです。

  • 検索候補がタップされた時
  • キーボードのリターンキーが押された時

ソースコード

import SwiftUI

struct ContentView: View {
    
    let colors: [String] = ["Red", "Blue", "Yellow", "Purple", "Orange", "Green", "Pink", "White", "Gray", "Black"]
    
    var filteredColors: [String] {
        if text.isEmpty {
            return colors
        } else {
            return colors.filter { $0.lowercased().contains(text.lowercased()) }
        }
    }
    
    @State private var text = ""
    
    var body: some View {
        NavigationView {
            List {
                ForEach(filteredColors, id: \.self) { color in
                    Text(color)
                }
            }
            .navigationTitle("Colors")
        }
        .searchable(text: $text, placement: .navigationBarDrawer(displayMode: .always)) {
            Text("Red").searchCompletion("Red")
            Text("Purple").searchCompletion("Purple")
            Text("Green").searchCompletion("Green")
        }
        .onSubmit(of: .search) {
            print("Submit")
        }
    }
}

動作確認

Simulator Screen Recording - iPhone 13 - 2022-08-15 at 17.12.40.gif

検索候補あり
Simulator Screen Recording - iPhone 13 - 2022-08-15 at 17.07.22.gif

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4