Formの入力時などPickerを利用する場合に、AのPickerで選択されている値を条件として、BのPickerで表示する項目を選択したい場面があります。
例えば、AのPickerに、[果物、野菜、肉]、BのPickerに[りんご、みかん、すいか、レタス、きゅうり、かぼちゃ、豚肉、鶏肉、牛肉]となっていて、AのPickerで果物を選択すると、りんご、みかん、すいかのみをBのPickerに表示した場合などです。
Pickerは通常、項目の表示とBindingに紐付いた値の変更を行い、Picker内でのactionはできません。
この状況に対応し、BindingExtensionを利用し機能を拡張し、対応する方法を紹介します。
◆動作検証環境
・ローカル環境:mac Catalina
・XCode:12.1
・SwiftUI:2.0
・XCode:12.1
・SwiftUI:2.0
スポンサードリンク
Bindingの拡張
下記の内容を参考にBindingの拡張を行います。
このコードを追加する事によって、Bindingの値にonChange が使えるようになります。
例)$value.onChange()
1 2 3 4 5 6 7 8 9 10 11 12 | extension Binding { func onChange(_ handler: @escaping (Value) -> Void) -> Binding<Value> { return Binding( get: { self.wrappedValue }, set: { selection in self.wrappedValue = selection handler(selection) }) } } |
onChangeメソッドに渡すメソッドの作成
Bindingの値のonChangeメソッドに渡す値を、メソッドとして作成します。
1 2 3 4 5 | func changeSlection(_ newValue: String){ SecondNo = newValue } |
上記の例では、使用中のPickerで選択されているselectionの値を、他の値に代入しています(他の値を他のPickerのselectionとすれば選択中にPickerを同じ値が他の値となります)。
Picker内でのonChangeメソッドの実装
あとは、Picker内でそれぞれのメソッドを実装して利用します。
1 2 3 4 5 6 7 8 | Picker(selection: $firstNo.Change(changeNo), label: Text("選択") { ForEach(0..<data.count, id: \.self){index in Text(data[index]).tag(dataSlection[index]) } } |
以上、SwiftUIで複数のPicker内であるselectionの値によって、他のselectionを変更する方法(BindingExtensionで機能拡張)を紹介しました。