【SwiftUI】Pickerの使い方

Pickerは複数の選択肢の中から1つの値をユーザーに選択させる為の部品です。
図のような回転ホイール表示が代表的なスタイルですが、プラットフォームによってスタイルが自動的に変わる特徴があります。

図1:Pickerの使い方

スポンサーリンク

環境

この記事の情報は次のバージョンで動作確認しています。

【Xcode】11.2.1
【Swift】5.1
【iOS】13.2.2
【macOS】Catalina バージョン 10.15.2
スポンサーリンク

基本的な使い方

最初の引数(selection)には選択値と連携するプロパティを指定します。
このプロパティの値は初期選択値として使用され、選択が変更されると値も同じく変更されます。
値が変更できるように、このプロパティは@State等で宣言しておく必要があります。
頭に$が付いているのは、プロパティの値では無く参照を渡し、Picker()がプロパティの値を更新可能にする意味があります。

@Stateについては、こちらの記事を参照して下さい。

【SwiftUI】@Stateの使い方
(2021/05/22 更新)SwiftUIのデータバインディングの仕組みの一つである、@Stateについて解説します。プロパティが更新された場合に、参照しているViewも同時に更新される仕組みが実現できます。その他のデータバインデ...

2番めの引数(label)は、Pickerに表示するラベルを指定します。View形式で指定できるので、単純なテキストだけでなく、シンボルやイメージなどを組み合わせ可能です。

最後に選択項目となるViewを列挙したクロージャーを記述します。
各選択項目に付加する.tag()は対象のViewを特定する目印です。この値がselectionに連携します。
tagの型はHashableプロトコルに準拠していれば良いので、数値、文字列等のSwift標準の型がほぼ使えますが、selectionで指定するプロパティと型を合わせる必要があります。

使用例

5種類のフルーツから1つを選択するPickerのサンプルです。

選択値と連携するプロパティ(selection)の初期値が、初期選択値として使用されます。
Pickerの選択を変更するたびに、selectionが更新されるので、画面下の選択値の値が再描画されます。

図2:基本的な使い方

スポンサーリンク

選択肢を繰り返し処理(ForEach)で設定する

ForEachを使った繰り返し処理で選択肢のリストを設定できます。
これを使って配列等のデータコレクションを選択肢リストに設定可能です。
ForEachを使った場合、.tag()による値の設定は不要となります。

ForEachには、【範囲指定】と【id指定】の2種類の繰り返しがあります。
詳しくは、こちらの記事で解説しています。

【SwiftUI】ForEachの使い方(1/2)
ForEachは繰り返し処理の中で、Viewを生成する仕組みです。名前の配列をループしてそれぞれをTextView化する、あるいはメニュー項目に追加するなどの動きを実現します。加えて、ForEachを使うとViewを手動で追加した場合に...

範囲指定による繰り返し

ForEachの【範囲指定】による繰り返しで、選択肢を設定するサンプルソースです。

配列(fruits)はフルーツ名が格納されており、ForEachによる繰り返し処理で、各要素を選択肢として設定します。
ForEachで生成されたデータ列のインデックス(0から始まる)が自動的にselectionと連携するので、.tag()による値の設定は不要です。
selectionの初期値として3が設定されているため、データ列4番目の=“バナナ”が初期選択値として表示されます。

id指定による繰り返し

ForEachの【id指定】による繰り返しで、選択肢を設定するサンプルソースです。

【id指定】による繰り返しの場合は、id自身がselectionと連携します。
この例ではidは配列fruitsの各要素ですので、連携するselectionも同じ型(String)で作成します。

なお、idに指定される値は基本的にユニークであるのが前提となります。
配列に内容の要素があった場合、想定外の動きになりますので注意してください。

勘違いしやすいselection連携の落とし穴

小学校の学年を選択させる為の次のようなコードがあります。

選択肢には1から6までの学年が表示され、初期値は3年生を設定しているつもりですが、想定通りに動きません。
初期値として4年生が選択されてしまいますし、1年生を選択すると、schoolYearには想定外の0が代入されます。
これは、【範囲指定】の繰り返しの場合、selectionはあくまでもデータ列のインデックス(0から始まる並び順)と連携するためです。

次にように【id指定】に変えて、ForEachのループアイテム値そのものと連携させると、想定した動きになります。

スポンサーリンク

表示スタイルの指定

Pickerは単独で使用した場合は回転ホイールスタイルですが、フォームで使用すると、図のように別画面に遷移して選択するスタイルに自動的に変わります。

図3:表示スタイルの指定

内部的にNavigationLinkを使って遷移する為、NavigationViewの中に記述する必要があります。

Xcode11.3および11.3.1に付属しているiOS13.3のシミュレーターでは、NavigationLinkの動作に不具合があり、2度続けて同じ画面に遷移できません。このサンプルを正しく動作させるには、実機あるいは、Xcode11.2.1に付属のシミュレーターで確認して下さい。

スタイルの任意指定

Modifierの.pickerStyle()を使用すると、Pickerの表示スタイルを任意に指定できます。
iOSでは現時点で指定できるのは次の2種類のみです。

WheelPickerStyle()

標準的な回転ホイールスタイルです。
Form内で指定すると、自動的に採用される画面遷移型の代わりに回転ホイール型で表示されます。

SegmentedPickerStyle()

水平リストに選択肢を並べる表示タイプで選択肢が少ない場合に最適です。
なお、このスタイルの場合ラベルは表示されません。

図:セグメントピッカースタイル

スポンサーリンク

ラベルを自由に配置する

Pickerの標準ラベルはレイアウトの柔軟性に乏しいので、自由にラベルを配置したい場合は、.labelsHidden()を使って標準ラベルを非表示にすると良いです。
非表示になった標準ラベルですが、VoiceOverによるスクリーンリーダーでは有効ですので、適切な文言をいれて残しておきましょう。

こちらは、ラベルを回転ホイールの上部に表示させるサンプルです。

図:ラベルを自由に配置する

スポンサーリンク

あわせて読みたい記事

【SwiftUI】DatePickerの使い方
DatePickerは日付と時間を選択するための専用Viewです。