LoginSignup
3
1

More than 3 years have passed since last update.

SwiftUIのContentClosureに定義出来るViewの数を増やす

Posted at

SwiftUIが提供する各種ViewのContentClosure引数内には定義出来るViewの数が決まっており、最大で10個のViewを配置することが出来ます。

struct ContentView: View {
    var body: some View {
        HStack {
            Text("1")
            Text("2")
            Text("3")
            Text("4")
            Text("5")
            Text("6")
            Text("7")
            Text("8")
            Text("9")
            Text("10")
        }
    }
}

多くのケースでは10個も配置出来れば十分なのですが、稀に11個以上のViewを配置したいケースも出てきますがこれはコンパイルエラーとなります。

struct ContentView: View {
    var body: some View {
        HStack {
            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` というコンパイルエラーになる
        }
    }
}

なぜこのようなコンパイルエラーが発生するのかというとSwiftUIのContentClosureに複数のViewを配置した場合の実態はTupleViewとなり、
Tuple内に定義出来るViewの数がデフォルトでは10個までしか定義されていないためです。

/**
以下のようにTuple内に配置出来るViewの数毎のI/Fが定義されており、これの最大数が10個となっています。
*/

extension ViewBuilder {
    public static func buildBlock<C0, C1>(_ c0: C0, _ c1: C1) -> TupleView<(C0, C1)> where C0 : View, C1 : View
}

extension ViewBuilder {
    public static func buildBlock<C0, C1, C2>(_ c0: C0, _ c1: C1, _ c2: C2) -> TupleView<(C0, C1, C2)> where C0 : View, C1 : View, C2 : View
}

型定義を見るとViewBuilderを拡張しているだけなので、より多くのViewを配置したい場合は独自にViewBuilderの型定義を追加すれば良いです。

/**
以下の要領で必要な数を内包するTupleViewを定義していけば良い。
*/

extension ViewBuilder {
    static func buildBlock<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10> (_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4, _ c5: C5, _ c6: C6, _ c7: C7, _ c8: C8, _ c9: C9, _ c10: C10) -> TupleView<(C0, C1, C2, C3, C4, C5, C6, C7, C8, C9, C10)> where C0: View, C1: View, C2: View, C3: View, C4: View, C5: View, C6: View, C7: View, C8: View, C9: View, C10: View {
        TupleView((c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10))
    }
}

struct ContentView: View {
    var body: some View {
        HStack {
            Text("1")
            Text("2")
            Text("3")
            Text("4")
            Text("5")
            Text("6")
            Text("7")
            Text("8")
            Text("9")
            Text("10")
            Text("11") // 上で11個を内包するTupleViewが定義されたので、ここでコンパイルエラーが発生しなくなる
        }
    }
}
3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1