SwiftUIでPickerを表示する方法【SwiftUI】

UIKitの「UIPickerView」からSwiftUIでは「Picker」というシンプルな名前になりましたが、全く感覚が違ったので色々と苦戦しました(Pickerに限らず、SwiftUIはUIKitとは全くの別物になった印象です)。

SwiftUIでPickerを表示する方法

struct ContentView: View {
    
    @State private var selection = 0
    
    let selections = [
        "C/C++",
        "Java",
        "Ruby",
        "PHP",
        "Objective-C",
        "Swift",
        "Kotlin"
    ]
    
    var body: some View {
        Picker(selection: $selection, label: Text("プログラミング言語")) {
            ForEach(0..<selections.count) { index in
                Text(self.selections[index])
            }
        }
    }
}

Pickerの第一引数に「@State」で宣言した変数を指定します(その際、接頭辞に「$」を付けることを忘れずに)。この変数に選択した要素のインデックスが自動的に格納されます。

一旦これで実行してみると以下のように表示されます。

UIKitでも見慣れたドラムタイプのピッカーです。PickerはPickerStyleを変更することで外観が変わるようになります。例として「SegmentedPickerStyle」を紹介しておきます。

Picker(selection: $selection, label: Text("プログラミング言語")) {
    ForEach(0..<selections.count) { index in
        Text(self.selections[index])
    }
}.pickerStyle(SegmentedPickerStyle())

なんだが、ニュースアプリなどでよく見るタブメニューのような感じになりましたね。この場合、ラベルが表示されなくなります。

では、もう少しSwiftUIっぽく(?)してみたいと思います。

「NavigationView」と「Form」で囲む

以下のようにNavigationViewとFormを使ってPickerを内包します。NavigationViewを忘れると選択肢を選択できなくなってしまうので忘れないように。

NavigationView {
    Form {
        Picker(selection: $selection, label: Text("プログラミング言語")) {
            ForEach(0..<selections.count) { index in
                Text(self.selections[index])
            }
        }
    }
}

実行すると以下のように別ページで選択するような感じに様変わりします。

最後に、選択肢の初期値を空欄にしておきたい場合ですが、予め先頭要素に空文字列を入れておくことで対応できますが、$selection-1を設定しておくことでも実現できます。初期値は空欄にしたいけど選択肢には空欄を入れたくない場合に有効かと思います(このやり方が良いのかは分かりませんが)。

以上です。