【Swift UI】Pickerの書式と使い方とスタイル変更!配列や列挙型

この記事からわかること
- SwiftのPickerとは?
- 構造や書式
- スタイルやセグメント型、tagの使い方
- Pickerに列挙型(enum)を指定する方法
- CaseIterableプロトコルとは?
index
[open]
\ アプリをリリースしました /
環境
- Xcode:15.0.1
- iOS:17.0
- Swift:5.9
- macOS:Sonoma 14.1
Swift UI:Pickerの構造と書式

Swift UIをのPicker(ピッカー)を使えば画像のような項目を選択できる表示を簡単に実装することができます。
書式
引数の中には選択されたインデックス番号(値)が格納されるselection
と表示されるラベルを定義できるlabel
が指定できます。しかしPickerのラベル部分はSwift. Xcode 12.2頃から仕様かバグにより表示されないようです。selection
は値を変更できるように@State
をつけて宣言しておきます。
選択肢はText()
などを使って表示部分を列挙していきます。.tag(数値)
をつけることで選択肢のインデックス番号を明示的に指定することができます。インデックス番号の並び順を変更しても実際に表示される順番はコードの順番になるので注意してください。
Pickerのポイントまとめ
- 引数selectionは@Stateをつけて宣言
- 引数selectionに選択された値が格納される
- ラベル部分はそのままでは表示されない
- .tag()でインデックス番号を指定できる
- .tag()で指定した順番と表示される順番は一致しない
簡易的なPickerの使い方
@State
を使ってselected
をbody
の外側に宣言しておきます。初期値として値を入れ込んでおけば選択肢のデフォルト値を変更することもできます。
selected
に格納されているのはインデックス番号なので選択肢の値を表示させることはできません。また.tag(数値)
をつけ忘れるとselected
には何も格納されないので注意してください。(この場合ずっと初期値0のまま)
配列を使った使い方
選択された値を表示させるには配列を使うと便利です。配列なのでForEach
を使って簡単に表示させる選択肢を構築することも可能です。また..tag()
の指定も不要になります。
あとは配列の中から選択されたインデックス番号と同じ番号の要素を表示させればOKです。
ForEach分の構文
ForEach
は配列の範囲を指定する際の構文が少し異なるのでそれによってPickerを扱う時も注意が必要です。
範囲は0..<配列の要素数
までなので配列.count
を使って指定します。
しかしこの構文ではNon-constant range: argument must be an integer literal
という警告が出てしまいます。これを防ぐためにはid : \.self
を追加します。また0..<lang.count
はlang.indices
で表現できます。
さらにlang.indices
とせずとも配列をそのまま指定してもOKです。その際はselectedLang
部分にインデックス番号ではなく値(文字列)自体が格納されます。
なので@State
で宣言しているselectedLang
はインデックス番号ではなく初期値に設定する文字列をそのまま格納しておきます。
配列をそのまま指定する場合
配列を使用するPickerのポイントまとめ
- ForEachを使って配列を選択肢にできる
- .tag()が不要になる
- 範囲は「0..<配列.count」や「配列.indices」、「配列」をそのまま指定
- Non-constant range警告抑制のため「id:\.self」
- 配列を直接渡す場合はselectionに番号ではなく値を格納
表示されないラベルを表示する
Swift. Xcode 12.2頃から仕様かバグかでデフォルトで表示されなくなってしまったらしいので表示させる方法をみていきます。元々は非表示にする際は.labelsHidden
を指定していました。
Text(ラベル)として表示させる
まずは普通にText(ラベル)
として表示させます。VStack
などで配置を調整してあげます。
navigationTitleとして表示させる
NavigationView
のnavigationTitle
を使って表示させます。Pickerに対して指定しないと表示されないので注意してください。
Sectionとして表示させる
Section
のヘッダーとして表示させるにはVStack
で囲んでおきます。
iPhoneの設定画面のように表示させる
NavigationView
とForm
を使えばiPhoneの設定画面のようなラベル名と選択項目が並んだレイアウトにすることができます。クリックすると別ページに移動し選択肢を選べるようになります。

Pickerのスタイルを変更する
PickerのスタイルはpickerStyle
モディファイアで簡単に変更できます。
SegmentedPickerStyle()

なぜかこのスタイルでビルドしようとすると以下のようなエラーが発生しましたが、問題なくビルドすることができました。

カスタムUIのセグメントピッカーを実装する方法

WheelPickerStyle()

WheelPickerStyle
ではアイテムの背景色などを変更することは可能ですがアイテム自体の高さや形を変更することはできないようです。変更したい場合はUIKitのUIPickerView
をUIViewRepresentable
で実装して以下の設定から変更するしかないかもです。
おすすめ記事:【SwiftUI】UIViewRepresentableの使い方!Coordinatorクラスとは?
※watchOSならdefaultWheelPickerItemHeight
メソッドで高さを変更することができます。
枠線と背景色をつける
Pickerに枠線や背景色をつけたい場合はViewのモディファイアを使用することで簡単に変更できます。
文字色を変更したい場合はtint
を使用します。
角を丸めた枠線
角を丸めた枠線はborderではできないので以下のようにすることで実装できます。
データに列挙型(enum)を指定する方法
Picker
で表示するデータに列挙型を渡すにはポイントとなる2つのプロトコルを指定します。
列挙型(enum)を指定する際のポイント
- Identifiableプロトコル
- CaseIterableプロトコル
Identifiable
プロトコルとはその構造の中に一意となる「識別子:identifier」を定義することを義務付けるプロトコルです。これに倣ってidプロパティ
を追加で定義します。
CaseIterableプロトコルとは?
CaseIterable
プロトコルはSwift 4.2から使用可能になったプロトコルで定義されているプロパティの値をコレクション形式で取得できるallCases
プロパティが実装されます。
あとはこれを組み合わせてPicker
の構文に当てはめるだけです。
Pickerに画像を使用する
画像を使用する方法は以下の記事を参考にしてください。

UIKitピッカーを実装するには?
UIKitで同じようなピッカービューを実装するにはcode>UIPickerView<< /code>クラスを使用します。詳細について以下の記事を参考にしてください。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。