VStack是否有最大限制?

时间:2019-10-15 15:17:51

标签: swiftui vstack

我从一个干净的项目开始,在VStack中添加了5个按钮和5个间隔,一切都很好。当我在底部添加第6个spacer时,代码突然不会编译并显示错误:“对成员'buildBlock()'的引用不明确”。

是什么导致此错误?这是与SwiftUI相关的错误吗?还是功能?这不是我第一次注意到VStack或HStack的条目数受到限制,这附近是否有一些文档?

不是完全可以激发信心,我应该切换回UIKit吗?

3 个答案:

答案 0 :(得分:1)

SwiftUI使用ViewBuilder来构建构成许多SwiftUI视图的视图,例如VStackHStackList等。如果您看一下{ {3}}文档中,您将看到buildBlock函数具有许多副本,每个副本具有不同数量的视图作为参数。具有最多视图数量的功能仅可容纳10个视图,这就是为什么您看到所观察到的限制的原因。解决此问题的一种方法是使用Group

VStack {
    Group {
        Text("Placeholder 0")
        Text("Placeholder 1")
        Text("Placeholder 2")
        Text("Placeholder 3")
        Text("Placeholder 4")
        Text("Placeholder 5")
        Text("Placeholder 6")
        Text("Placeholder 7")
        Text("Placeholder 8")
        Text("Placeholder 9")
    }
    Group {
        Text("Other Placeholder 10")
        Text("Other Placeholder 11")
        Text("Other Placeholder 12")
        Text("Other Placeholder 13")
        Text("Other Placeholder 14")
        Text("Other Placeholder 15")
        Text("Other Placeholder 16")
        Text("Other Placeholder 17")
        Text("Other Placeholder 18")
        Text("Other Placeholder 19")
    }
}

尽管如果您想要20个彼此非常相似的视图,建议您使用ForEach之类的方法,以免使视图过于膨胀。仅当> 10个视图确实是唯一的时,才应使用上述解决方法。即便如此,更SwiftUI-y的方法是将这些视图拆分为更小的视图:

VStack {
    SingleDigitPlaceholders()
    TeensPlaceholders()
}

struct SingleDigitPlaceholders: View {
    var body: some View {
        ForEach(0..<10) { i in
            Text("Placeholder \(i)")
        }
    }
}
struct TeensPlaceholders: View {
    var body: some View {
        ForEach(10..<20) { i in
            Text("Other Placeholder \(i)")
        }
    }
}

当然,在此特定示例中,您只能在原始视图中具有两个ForEach,但是在更复杂的情况下,问题仍然存在。例如,在具有许多元素的表单中(例如,在工作申请表中:名字,姓氏,地址,电话号码文本字段,教育下拉菜单,日期字段等),您仍然可以将一个视图拆分为较小的组件(在工作申请示例中-个人信息视图,教育信息视图等)。

答案 1 :(得分:0)

VStack中最多可以有10个孩子(以及ZStackHStack等)。严格来说,这与它们的实现以及@ViewBuilder闭包的实现有关。请看下面的界面(您可以通过xCode找到它们,为了使其更具可读性,我对其进行了一些简化):

public struct ViewBuilder {    
    /// Builds an empty view from an block containing no statements, `{ }`.
    public static func buildBlock() -> EmptyView

    /// Passes a single view written as a child view (e..g, `{ Text("Hello") }`) through
    /// unmodified.
    public static func buildBlock<Content>(_ content: Content) -> Content where Content : View
}

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
}

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

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

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

extension ViewBuilder {
    public static func buildBlock<C0, C1, C2, C3, C4, C5, C6>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4, _ c5: C5, _ c6: C6) -> TupleView<(C0, C1, C2, C3, C4, C5, C6)> where C0 : View, C1 : View, C2 : View, C3 : View, C4 : View, C5 : View, C6 : View
}

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

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

extension ViewBuilder {
    public 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个孩子来建立这种视图。每个buildBlock方法都将确切数量的视图用作参数。这是因为@ViewBuilder闭包,至少目前不支持可变参数。

一种解决方法可以是:

struct ContentView: View {
    var body: some View {
        VStack {
            Group {
                //10 views here
            }

            Group {
                //10 views here
            }
        }
    }
}

答案 2 :(得分:0)

在我的视图周围添加组后,我有 6 个视图,我仍然在调用错误中收到 Extra 参数。

这就是我为修复错误所做的。

struct ContentView: View {
    var body: some View {
        VStack {
            Group {
                //3 views here
            }

            Group {
                //3 views here
            }
        }
    }
}