本記事について
本記事は、以下のセッションを見て改めて重要だと思った内容を復習しながらメモしたものです。
イントロ
SwiftUIは新しいアプリや機能を構築する際に最適なツールと述べています。
その理由は、下記の通りです。
Rich Feature Set
SwiftUIは豊富な機能セットを提供しています。開発者はさまざまな機能を簡単に実装することができます。
Less Code
これらの豊富な機能を実装するために必要なコード量が少なくて済みます。
Incremental Adoption
アプリ全体をSwiftUIで書く必要はありません。
既存のアプリに徐々にSwiftUIを取り入れることができ、必要な部分だけを更新することが可能です。
Viewの基礎
SwiftUIのViewには3つの特徴があります。
- Declarative(宣言的)
- Compositional(構成型)
- State-Driven(状態駆動)
1. Declarative(宣言的)
UIKitのような命令的な実装では、ゴールに到達するまでの各ステップが必要ですが、宣言的な実装では、期待する結果に焦点を当てます。SwiftUIは命令的、宣言的の2つの要素を持っています。
下記に具体的な実装例を示します。
実現したいUIを宣言
Text("test")
Image(systemName: "gear")
Button("Tap") {
// ボタン押した時の処理
}
HStackやVStackなどを使えば、それぞれのパーツの組み合わせを作る
HStack {
Image(systemName: "globe")
Text("Hello")
}

Listなどの他のコンテナにも適用
List(0..<5) {_ in
HStack {
Image(systemName: "globe")
Text("Hello")
}
}

宣言的にUIを配置して、命令的に状態の変更を加える
Button("Add money") {
let money = Money(100)
moneyList.append(money)
}
なぜStructなのか?
Viewは、UIの現在の状態を示し、時間とともに命令を受け取って更新されます。長期間使うインスタンスではないため、classではなくstructを使用しています。
2. Compositional(構成型)
コンテナビューの再配置が簡単
HStack {
Label("hello", systemImage: "gear")
Spacer()
Text("walking")
}
↓
HStack {
Image("pork")
.resizable()
.frame(width: 50, height: 50)
VStack(alignment: .leading) {
Label("hello", systemImage: "gear")
Text("walking")
}
Spacer()
}


View Modifierは順序に基づいて定義される
Image("dog")
.clipShape(.circle) // 2つ目
.shadow(radius: 20) // 3つ目
.overlay {
Circle().stroke(.green, lineWidth: 5) // 4つ目
}

3. State-Driven(状態駆動)
状態が変化すると自動的に最新の状態に保つため、更新のバグを防ぐことができます。
@State
を用いた状態管理
ボタンが押された後、内部状態でcountがインクリメントされます。
countの変化がViewに通知され、bodyを呼び出すことで値が変更されます。
struct CounterView: View {
@State private var count: Int = 0
var body: some View {
VStack {
Text("\(count)")
Button("Add Count") {
count += 1
}
}
}
}
@Binding
を用いた状態管理
親子関係のViewを扱う際には、子View(CounterView)がBindingを入力として受け取るように更新します。これにより、双方向で状態変化を参照でき、親Viewの更新が同期されます。
struct CounterView: View {
@Binding var count: Float
var body: some View {
VStack {
Text("\(count)")
Button("Add Count") {
count += 0.1
}
}
}
}
struct ContentView: View {
@State private var count: Float = 0.0
var body: some View {
VStack {
Gauge(value: count, in: 0...1) {
Text("Counter")
}
CounterView(count: $count)
}
}
}
最後に
WWDC24で基礎的なセッションが公開されましたが、改めて見ると実は知らなかった要素や、感覚的には理解していたものの言語化できていなかった要素があり、良い復習になりました。