【SwiftUI】VStackでExtra argument in callの原因とエラー解決!ViewBuilder構造体とは

この記事からわかること
- SwiftUIのVStackで発生したエラー
- Extra argument in callの原因と解決方法
- ViewBuilder構造体とは?
- buildBlockメソッドの使い方
index
[open]
\ アプリをリリースしました /
エラー:Extra argument in callとは?
SwiftUIでアプリ開発中にVStack
でビューを縦に並べていた際に以下のようなエラーが発生しました。
発生したコード
struct ContentView: View {
var body: some View {
VStack {
Text("1")
Text("2")
Text("3")
Text("4")
Text("5")
Text("6")
Text("7")
Text("8")
Text("9")
Text("10")
Text("11")
}
}
}
発生したエラー
Extra argument in call
// 翻訳:呼び出しの余分な引数
このエラーは渡された引数の数が合わない際に発生するエラーのようです。今回はVStack
の引数に11個のTextView構造体を渡したところ発生しました。
VStackの定義
おすすめ記事:【Swift UI】HStack/VStack/ZStackの違いと組み込む方法!LazyHStackの使い方
VStackの定義を見てみると3つの引数が定義されています。
@frozen public struct VStack<Content> : View where Content : View {
@inlinable public init(alignment: HorizontalAlignment = .center, spacing: CGFloat? = nil, @ViewBuilder content: () -> Content)
}
- alignment: HorizontalAlignment = .center:ビューの配置
- spacing: CGFloat? = nil:ビュー間の余白
- @ViewBuilder content: () -> Content:スタックのコンテンツを作成するViewBuilder
今回エラーが発生している引数はcontent
部分です。ここはViewBuilder
構造体のみを受け取ることになっています。
ここだけを見ると複数のビューを受け取れる理由がよくわかりません。これを解決するためにViewBuilder構造体
の定義を見ていきます。
ViewBuilder構造体とは?
ViewBuilderとはクロージャからビューを構築するために使用される構造体です。VStack
やHStack
などをインスタンス化して使用する際は()
ではなく{}
を使用しているのもこのViewBuilder
が関連してきています。
おすすめ記事:【Swift】クロージャとは?関数との違いとキャプチャの意味
ViewBuilderの定義を見てみるとbuildBlock
メソッドが怪しそうです。
ViewBuilderの定義
@resultBuilder public struct ViewBuilder {
static func buildBlock<Content>(_ content: Content) -> Content where Content : View
つまりVStack
の引数に渡すViewBuilderのbuildBlockメソッドを使用してTextなどのビューを渡しているようです。なので以下のコードでも問題なく動作しました。
struct ContentView: View {
var body: some View {
VStack {
ViewBuilder.buildBlock(
Text("1")
)
}
}
}
エラーの原因
先ほどは1つのビューを返す場合のメソッドでしたが、さらに以下のメソッドも定義されていました。引数にはC0〜C9
までを受け取れるメソッドのようです。ContentsのCでしょうか?
そしてこの数が10個です。定義されていた最大の引数を保持していたのがこのメソッドだったのでViewBuilder
では最大10個のビューまでしかクロージャの中に含めることができないようです。
static func buildBlock<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>(
_ c0: C0,
_ c1: C1,
_ c2: C2,
_ c3: C3,
_ c4: C4,
_ c5: C5,
_ c6: C6,
_ c7: C7,
_ c8: C8,
_ c9: C9) -> TupleView<(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9
)> where C0 : View, C1 : View, C2 : View, C3 : View, C4 : View, C5 : View, C6 : View, C7 : View, C8 : View, C9 : View
10個以上のビューを含める方法
ViewBuilder
構造体に含めることができるビューが10個までと分かりましたが、それ以上のビューを含めることができないわけではありません。
ViewBuilder
の子ビューが10個までと言うことなのでHStack
やGroup
などで囲うことで10個以上のText
を表示させることが可能でした。
struct ContentView: View {
var body: some View {
VStack {
HStack{
Text("1")
Text("2")
Text("3")
}
Group{
Text("4")
Text("5")
Text("6")
}
VStack{
Text("7")
Text("8")
Text("9")
}
Text("10")
Text("11")
}
}
}
私がSwift UI学習に使用した参考書
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。