[SwiftUI] searchable の使い方

SwiftUI2021

     

TAGS:

macOS12, iOS 15 で導入された searchable の使い方を説明します。

環境&対象

以下の環境で動作確認を行なっています。

  • macOS Monterey 12.4 beta4
  • Xcode 13.3.1
  • iOS 15.4

検索ビュー

以下のような 検索キーワードを入力することができる UI をもつアプリは多くあります。

SearchBar_ios
SearchBar_macos

UIKit であれば UISearchBar 、AppKit であれば NSSearchField を使って実装することができました。

macOS12, iOS 15 で、同様の UI を提供できる searchable という View Modifier が追加されましたので説明します。

パラメータ

パラメータは、以下の3つです。(initializer によっては指定不要です)
- text
- placement
- prompt

text

Search Bar で入力された文字列が反映されます。 Binding<String> を渡します。

placement

Search Bar の配置位置を指定することができます。

automatic
iOS,iPadOS,macOS では、toolbar 指定と同じ。tvOS,watchOS では、他要素と並べられます。
navigationBarDrawer
navigation ビューの上部から引き下げる操作をしたときに表示されます。(iOS, watchOS のみ)
sidebar
iOS,iPadOS では、NavigationView で関連づけられた sidebar に表示されます。macOS では、sidebar の他要素と並べられます。
toolbar
iOS/watchOS では、引き下げる操作をしたときに表示されます。iPadOS では、navigationBar に表示され、macOS では、toolbar に表示されます。
MEMO
現時点では、上記で指定できる箇所以外への設置はできないようです。
特に不自然な箇所に配置されることはありませんが、具体的な箇所に指定することはできないようです。

prompt

入力前に、薄いグレーで表示される プロンプト文字列指定です。

どのような文字入力を期待しているかを説明するために使用されます。

クリアボタン

searchable で表示される search bar には、自動で クリアボタンが追加されます。
(もともと HIG でもクリアボタンの追加が推奨されています)

クリアボタンは、文字が入力されていない時には表示されず、文字入力後に 表示されるようになります。

もちろん、ボタンが押されると searchable に渡されている文字列はクリアされます。

onSubmit

searchable の導入に合わせて、onSubmit に新しいオプションが追加されています。
search bar でエンター等の入力確定動作を行うと closure が実行されます。


      .onSubmit(of: .search) {
          // do something
      }

1文字づつのタイプに合わせてではなく、入力の確定によって動作したいときには、onSubmit を使用します。

searchable 使用例


//
//  ContentView.swift
//
//  Created by : Tomoaki Yagishita on 2022/05/08
//  © 2022  SmallDeskSoftware
//

import SwiftUI

let data = ["One", "Two", "Three", "Four", "Five"]

struct ContentView: View {
    @State private var searchKeyword: String = ""
    
    var body: some View {
        NavigationView {
            List(filteredData, id: \.self) { element in
                Text(element)
            }
            .searchable(text: $searchKeyword, placement: .toolbar, prompt: "search keyword")
            .navigationTitle("List")
        }
            .padding()
    }
    
    var filteredData: [String] {
        get {
            if searchKeyword == "" { return data }
            return data.filter({$0.contains(searchKeyword)})
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

上記のようなコードで、iOS/macOS それぞれ以下のようのな外観となります。

SearchBar_ios
SearchBar_macos

注意点

非常にシンプルにできている searchable ですが、気をつけるべき点があります。

クリアしても、onSubmit は実行されない

クリアボタンを押すと、文字列は、空文字になりますが、onSubmit の closure は、実行されません。
つまり、クリアボタンは、あくまで 検索文字列をクリアしているのであり、それを 入力確定しているという扱いではないようです。

searchable と紐づけられた文字列を使用して、検索ビューの更新等を実装しているのであれば良いのですが、onSubmit で検索処理等をおこなっていると、この点が盲点となります。

クリアボタンを押された時に検索結果のビューを更新したいとき等には、onSubmit によっての更新を期待することはできず、独自に実装する必要があります。

例えば、以下のように onChange を使用して、文字列の変更を監視することで クリアボタンを押された時の動作を定義することが可能です。


            .onChange(of: searchKeyword) { newValue in
                // do something
                if newValue == "" {
                    // clear button pushed
                }
            }

まとめ

UISearchBar, NSSearchField を置き換える UI searchable の使い方 を説明しました。

searchable の使い方
  • searchable は、UISearchBar/NSSearchField の SwiftUI 版
  • searchable には、Binding<String> を渡すと入力された文字列に更新される
  • searchable には、文字入力されると クリアボタンが表示される
  • onSubmit に、searchable での入力終了時に実行できるオプションが追加された
  • クリアボタンで文字列をクリアしても、onSubmit は呼ばれない

iOS では、リストを少し引き下げるジェスチャを行わないと、search bar は表示されません。

説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。

コメントを残す

メールアドレスが公開されることはありません。