より便利になった入出力機能──Advanced controls
アプリの入出力を担うUIに関して機能が強化されました。主要な変更点について、Forms/Controls/Tablesの3つでまとめられています。
分類 | 概要 |
---|---|
Forms | フォームの構成要素 |
Controls | UI部品 |
Tables | 複数のリストをまとめたUI |
それぞれの項目について簡単なサンプルコードとともに紹介します。
Froms
Formとは、TextFieldやDatePickerなどの入力用のUI部品をまとめてスクロール上に表示できるUIのことです。Formsとは、Formの構成要素をまとめて指します。
フォームの項目を構造体で管理する
そのFormに、左側に項目名/右側に値を表示するLabeledContent構造体が新しく追加されました。LabeledContentの利用例は次の通りです。
Form { LabeledContent("Label", value: "Content") }
LabeledContent構造体を引数に項目名、表示する値を引数に配置します。
リストのような表示だけでなく、コンテンツ部分にUIを伴って表示したい場合は次のようにLabeledContent構造体内でブロックを分けます。
LabeledContent { Stepper(value: $value, in: 0...10.0) { Text(value.formatted(.number)) } } label: { Label("Count", systemImage: "hammer") }
最初のブロックにコンテンツに表示するUI、labelブロックにラベルに表示するUIを記述します。コンテンツのブロックが先で、ラベルを後のブロックに記述します。
LabeledContentを利用することで、ラベルとUIを並べたフォーム画面を作成することが容易になります。
複数のToggleをまとめて管理する
ON/OFF状態を切り替えるToggleについて、複数のToggleの値をまとめて一括で管理する機能が追加されました。
struct SettingsModel: Identifiable { // (1) まとめて管理するToggle項目 var id = UUID() var name: String var isToggle = false } struct ContentView: View { @State private var list = [ // (2) サンプルのToggleのリスト SettingsModel(name: "Push", isToggle: false), SettingsModel(name: "SMS", isToggle: false), SettingsModel(name: "Email", isToggle: false) ] var body: some View { Form { DisclosureGroup { List($list) { $list in // リストの各Toggle Toggle(list.name, isOn: $list.isToggle) // (3) } } label: { // リストの各Toggle項目をまとめるToggle Toggle(sources: $list, isOn: \.isToggle, label: { // (4) Text("All Natifications") }) }.disclosureGroupStyle(.automatic) } } }
複数のToggleを1つのToggleの配下にまとめる際には、最初にまとめて管理するToggle項目を表す構造体を定義します(1)。各Toggle項目をバインディング変数で定義し(2)、各Toggleをリストで表示します(3)。次に、各Toggleをまとめる親Toggleを定義します(4)。親Toggleでは、各Toggle項目をまとめるToggleを引数sourceに(2)で定義した変数、引数isOnに(1)で定義したBool型プロパティ、表示するラベルを指定します。Bool型プロパティは、「\.プロパティ名」の書式で記述します。
Toggle項目に当たる構造体の定義/各項目のToggleの配置/それらをまとめるToggleの配置、の3段階の処理で複数のToggleをまとめることができます。
Controls
Controlとは、UI部品の総称です。冒頭の紹介動画では入力系UIの制御に関して新しく追加された機能として、複数行のテキスト入力と複数の日付選択が紹介されています。
struct ContentView: View { @State var text: String = "複数の\n text入力" @State var selectedDates: Set<DateComponents> = [] var body: some View { Form { Section("Text Input") { TextField("", text: $text, axis: .vertical) // (1) 複数行の入力を可能に .lineLimit(5...10) } Section("Multi DatePicker") { MultiDatePicker("", selection: $selectedDates) // (2) 複数の日付選択 .frame(height: 300) .padding() .background { RoundedRectangle(cornerRadius: 16) .fill(Color.gray.opacity(0.2)) } .padding() } } } }
(1)複数行のテキスト入力UIとして、TextField構造体がaxis引数で入力欄のスクロール方向を指定できるようになりました。サンプルでは垂直方向(Axis.vertical)としています。lineLimitメソッドで入力するテキストの最小/最大行を指定できます。
(2)複数の日付選択は、新しく追加されたMultiDatePicker構造体で行います。選択した日付は、カレンダーの選択した日付がバインディング変数に入ります。
Tables
Tableは、複数のリストをまとめてテーブルの形式で表示を行う構造体です。複数のリストをまとめたり、リストの一部を折り畳む/展開する表示も可能です。Chartsのサンプルで利用したデータをテーブルで表示する例は次の通りです。
struct ContentView: View { var body: some View { Table(MonthAmount.examples) {. // テーブルを定義 TableColumn("Month", value: \.month). // 行単位でカラムを表示 (1) TableColumn("Amount") { monthAmount in. // (2) Text(String(monthAmount.amount)) } }.padding() } }
テーブルはTable構造体で定義します。Tableブロック内で、行単位でカラムをTableColumn構造体で指定します(1)。表示するカラムの内容がString型以外の場合は、(2)のようにクロージャ内でString型に変換して表示します。
まとめ
今回は「What's new in SwiftUI」の前半部分で紹介されたSwiftUI 4の新しい機能について説明しました。次回は、後半部分について説明します。