Highlight
SwiftUI 入門から中級者向けの基礎整理セッションです。講演者は「ペット trick ランキング」アプリを通じて、最も基本的な View 概念から List、Navigation、カスタムコンポーネント、状態管理、他フレームワークとの統合までを解説します。
主要内容
SwiftUI 入門から中級者向けの基礎整理セッションです。講演者は「ペット trick ランキング」アプリを通じて、最も基本的な View 概念から List、Navigation、カスタムコンポーネント、状態管理、他フレームワークとの統合までを解説します。
核心内容は 3 つの層に分かれます。第 1 層は View の本質: SwiftUI の View は宣言的な記述であり、長期間存在するオブジェクトインスタンスではありません。状態が変化するたびに SwiftUI は View body を再評価し、新しい記述を生成して効率的にレンダリングを更新します。第 2 層は合成: コンテナビュー(HStack、VStack、List)と View Modifier でシンプルなビューを複雑な UI に組み合わせます。第 3 層は状態駆動: @State、@Bindable、@Environment などのプロパティラッパーでデータ依存を宣言し、SwiftUI が UI 更新を自動処理します(00:07)。
セッションでは SwiftUI が他フレームワークとどう共存するか — UIKit 相互運用、SwiftData 永続化、Widget 拡張 — についても相当な時間を割き、アプリ全体を書き直すことなく段階的採用をネイティブにサポートすることを強調しています(21:08)。
詳細
宣言的 View の本質
SwiftUI の View は値型(struct)であり、長期間存在するオブジェクトインスタンスではありません。状態が変化するたびに SwiftUI は View body を再評価し、新しい記述を生成して効率的にレンダリングを更新します。ビューのライフサイクルを手動管理する必要はなく、「UI がどうあるべきか」を記述するだけです(00:09)。
// 基本的な View 宣言
HStack {
Label("Pet Tricks", systemImage: "pawprint")
Spacer()
Text("Rank")
}
キーポイント:
HStackは子ビューを水平に並べるコンテナビューLabelはアイコンとテキストを組み合わせる SwiftUI 組み込みの複合コントロールSpacerは残りのスペースを自動的に占有し、レイアウトの整列を実現
List と ForEach の組み合わせ
List は最もよく使われるコンテナビューの 1 つです。コレクションパラメータを受け取り、内部で ForEach ビューを自動作成して各要素の行を生成します。再利用とスクロール性能を手動管理する必要はありません(02:56)。
// List がコレクションの各要素の行を自動作成
List(pets) { pet in
HStack {
Text(pet.name)
Text(pet.trick)
}
}
キーポイント:
ListのコレクションパラメータがForEachビューを自動作成- 各要素が
HStack行ビューに対応 - SwiftUI がスクロール性能とビュー再利用を自動処理
View Modifier のチェーン
View Modifier は SwiftUI のもう 1 つの核心パターンです。基本ビューを「修飾」し、修飾された新しいビューを返します。複数の Modifier をチェーンでき、効果の階層を明確に形成します(06:17)。
// View Modifier のチェーン
Image("whiskers")
.clipShape(Circle())
.shadow(radius: 5)
.overlay(Circle().stroke(Color.green, lineWidth: 2))
キーポイント:
clipShape(Circle())で画像を円形にクロップshadow(radius:)でシャドウ効果を追加overlayで上に緑色のボーダーを重ねる- Modifier の順序が効果の適用順序を決定
カスタム View のカプセル化
UI が複雑になると、ビュー階層をカスタム View にカプセル化できます。カスタム View は View プロトコルに準拠し、body プロパティを提供するだけです。View は値型なので、ビューを分割しても性能に悪影響はありません(07:02)。
// カスタム View のカプセル化
struct PetRow: View {
let pet: Pet
var body: some View {
HStack {
ProfileImage(for: pet)
VStack(alignment: .leading) {
Text(pet.name)
Text(pet.trick)
}
}
}
private var profileImage: some View {
Image(pet.imageName)
.clipShape(Circle())
.shadow(radius: 5)
}
}
キーポイント:
- カスタム View に入力パラメータとしてプロパティを追加可能
private計算プロパティでコードを整理List(pets) { PetRow(pet: $0) }など任意の場所で再利用可能
状態駆動の UI 更新
SwiftUI の 3 つ目の核心機能は状態駆動です。状態が変化すると、SwiftUI はその状態に依存する View body を自動的に再計算し UI を更新します。手動 UI 更新のボイラープレートと更新漏れバグを排除します(08:50)。
// 状態駆動の条件レンダリング
struct PetRow: View {
let pet: ObservablePet
var body: some View {
HStack {
Text(pet.name)
if pet.hasAward {
Image(systemName: "trophy.fill")
}
}
}
}
キーポイント:
pet.hasAwardが変化すると SwiftUI がbodyを自動再計算- 条件レンダリングが自動更新。手動リフレッシュ不要
- SwiftUI が View body で使用されるプロパティを追跡し、依存関係を構築
@State と Binding
@State は View の内部状態ソースを作成します。Binding は他の View の状態への双方向参照です。Binding により子 View が親 View の状態を変更でき、状態共有を実現します(09:30)。
// @State で内部状態を作成
struct RatingView: View {
@State private var rating = 0
var body: some View {
HStack {
Button("-") { rating -= 1 }
Text("\(rating)")
Button("+") { rating += 1 }
}
}
}
// Binding で状態を共有
struct RatingContainer: View {
@State private var rating = 0
var body: some View {
VStack {
Gauge(value: rating, in: 0...10)
RatingView(rating: $rating) // Binding を渡す
}
}
}
struct RatingView: View {
@Binding var rating: Int // Binding を受け取る
var body: some View {
HStack {
Button("-") { rating -= 1 }
Text("\(rating)")
Button("+") { rating += 1 }
}
}
}
キーポイント:
@Stateで SwiftUI がプロパティストレージを管理$プレフィックスで Binding を作成し、双方向バインディングを実現- 子 View が Binding を変更すると親 View の状態が更新
- 状態共有で複数の View が同期更新
アニメーション統合
SwiftUI のアニメーションは状態駆動の更新メカニズムの上に構築されています。withAnimation で状態変化をラップすると、SwiftUI がデフォルトアニメーションを自動適用します。アニメーションカーブやトランジション効果もカスタマイズ可能です(11:40)。
// 状態駆動のアニメーション
Button("+") {
withAnimation {
rating += 1
}
}
// カスタムトランジション効果
Text("\(rating)")
.contentTransition(.numericText())
キーポイント:
withAnimationが状態変化をラップしてアニメーションをトリガー.numericText()トランジションは数値変化に適している- アニメーションは宣言的。タイミングの手動制御不要
適応型コントロール
SwiftUI のコントロールは正確な視覚的構造ではなく「目的の記述」です。Button は「ラベル付きアクション」を宣言するだけで、具体的なスタイルはコンテキストに応じて自動適応します。リストではスワイプ操作、メニューではメニュー項目になります(14:09)。
// 適応型検索
List(pets) { pet in
PetRow(pet: pet)
}
.searchable(text: $searchText)
キーポイント:
.searchablemodifier が検索機能を自動追加- iOS ではリスト上にオーバーレイ、macOS ではドロップダウンメニューを表示
- コントロールがコンテキストに応じてスタイルを自動適応
プラットフォーム適応と相互運用
SwiftUI はすべての Apple プラットフォームをサポートします。同じコードが異なるプラットフォームのデザインガイドラインに自動適応します。macOS はマルチウィンドウ、watchOS はデジタルクラウンスクロール、visionOS は空間コンテンツをサポートします(15:54)。
// watchOS デジタルクラウンスクロール
.scoreboard
.digitalCrownRotation($rating, from: 0, through: 10)
// UIKit 相互運用
struct UIKitView: UIViewRepresentable {
func makeUIView(context: Context) -> UIViewType {
// UIKit ビューを作成
}
func updateUIView(_ uiView: UIViewType, context: Context) {
// UIKit ビューを更新
}
}
キーポイント:
.digitalCrownRotationでデジタルクラウン制御を有効化UIViewRepresentableで SwiftUI 内に UIKit ビューを埋め込みUIHostingControllerで UIKit 内に SwiftUI ビューを埋め込み
重要ポイント
-
UIKit からの移行: 一度にすべて書き直そうとしない。 SwiftUI の
UIViewRepresentableとUIHostingControllerにより、UIKit 内に個別の SwiftUI ビューを埋め込む、またはその逆が可能です。独立した境界の明確な機能(設定ページ、オンボーディングなど)を見つけ、まず SwiftUI で実装し、チームの学習曲線と開発効率を検証しましょう。 -
新規プロジェクトは SwiftUI を直接使用。 Apple はすでに多くの新規アプリで SwiftUI を使用しており、フレームワークの成熟度はもはや問題ではありません。SwiftData でデータ永続化を組み合わせ、
@Queryで UI とデータを自動同期 — 技術スタック全体が宣言的です。ただし、高度にカスタマイズされたスクロール動作や複雑なタッチイベント処理など、一部の高度なカスタマイズシナリオでは UIKit に戻る必要がある場合があります。 -
View の値型特性を活用してコードを分割。 大きな View を小さな View に分割し、各 View が明確な入力パラメータを受け取るようにします。1 つの View の body に 200 行書かない — 5 つのサブ View に分割すれば保守性が向上し、性能への悪影響もありません。SwiftUI は変化した状態に依存する View のみを効率的に更新します。
関連セッション
- What’s new in SwiftUI — SwiftUI 2024 の新機能と改善の詳細解説
- Bring SwiftData to your SwiftUI app — SwiftUI で SwiftData 永続化を統合
- SwiftUI for watchOS — Apple Watch 向け SwiftUI 開発の実践
- Advances in SwiftUI Animation — SwiftUI アニメーションシステムの高度な使い方
- Build SwiftUI apps for visionOS — visionOS 向け SwiftUI 空間コンピューティングアプリの構築
コメント
GitHub Issues · utterances