SwiftUIでアプリ開発をしていると、必ず目にする@ViewBuilder
。この記事では、@ViewBuilder
とは何か、なぜ必要なのかをわかりやすく解説します。
@ViewBuilderって何?
@ViewBuilder
は、SwiftUIで複数のビューを簡潔に記述するための仕組みです。
通常のSwift関数では、戻り値は1つしか返せませんよね。でも、SwiftUIでUIを作るときは、複数のビューを並べて配置したいことがほとんどです。@ViewBuilder
はこの問題を解決してくれます。
実例で理解する
普通に書けるのはなぜ?
SwiftUIを書いていて、こんなコードを自然に書いたことがあるはずです:
struct ContentView: View {
var body: some View {
Text("こんにちは")
Text("SwiftUIへようこそ")
Image(systemName: "star.fill")
}
}
実は、このbody
には暗黙的に@ViewBuilder
が適用されているんです。だから複数のビューを並べて書けるんですね。
条件分岐も自然に書ける
ログイン状態に応じて表示を変えたい場合も、直感的に書けます:
var body: some View {
if isLoggedIn {
Text("ようこそ、\(userName)さん")
Button("ログアウト") { logout() }
} else {
Text("ログインしてください")
Button("ログイン") { showLogin() }
}
}
これも@ViewBuilder
のおかげです。
自分でも使ってみよう
カスタムビューコンテナを作る
@ViewBuilder
を使うと、再利用可能なカスタムコンテナを簡単に作れます:
struct CardView<Content: View>: View {
let title: String
@ViewBuilder let content: () -> Content
var body: some View {
VStack(alignment: .leading, spacing: 12) {
Text(title)
.font(.headline)
content()
}
.padding()
.background(Color(.systemBackground))
.cornerRadius(12)
.shadow(radius: 2)
}
}
このカードは、こんな風に柔軟に使えます:
CardView(title: "ユーザー情報") {
Text("名前: 田中太郎")
Text("メール: tanaka@example.com")
Button("編集") { }
}
CardView(title: "設定") {
Toggle("通知を受け取る", isOn: $notificationsEnabled)
Toggle("ダークモード", isOn: $darkModeEnabled)
}
ヘルパー関数を作る
繰り返し使うビューの組み合わせを関数化できます:
struct ProfileView: View {
@ViewBuilder
func sectionHeader(_ title: String) -> some View {
Text(title)
.font(.title2)
.fontWeight(.bold)
Divider()
}
var body: some View {
ScrollView {
VStack(alignment: .leading, spacing: 20) {
sectionHeader("基本情報")
// 基本情報の内容
sectionHeader("アカウント設定")
// 設定の内容
}
.padding()
}
}
}
知っておきたい制限事項
@ViewBuilder
は便利ですが、いくつか制約があります:
1. 最大10個まで
一度に並べられるビューは10個までです。それ以上必要な場合は、Group
やVStack
でまとめましょう:
// ❌ これはエラー
var body: some View {
Text("1")
Text("2")
// ... 11個以上
}
// ✅ グループ化すればOK
var body: some View {
Group {
Text("1")
Text("2")
// ...
}
Group {
Text("11")
Text("12")
}
}
2. for-inループは使えない
通常のfor-inループは使えませんが、ForEach
を使えば解決です:
// ❌ これは使えない
for item in items {
Text(item)
}
// ✅ ForEachを使う
ForEach(items, id: \.self) { item in
Text(item)
}
3. 変数宣言はできない
@ViewBuilder
内では、let宣言などはできません:
// ❌ エラー
var body: some View {
let greeting = "こんにちは"
Text(greeting)
}
// ✅ 外で宣言する
var body: some View {
Text(greeting)
}
private var greeting: String {
"こんにちは"
}
まとめ
@ViewBuilder
は、SwiftUIの宣言的なUI構築を支える重要な機能です。この仕組みのおかげで、私たちは複雑な条件分岐や複数のビューを、まるで普通のコードを書くように自然に記述できます。
カスタムビューやヘルパー関数を作るときは、積極的に@ViewBuilder
を活用して、再利用可能で読みやすいコードを書いていきましょう!