我从一个干净的项目开始,在 VStack 中添加了 5 个按钮和 5 个垫片,一切都很好。当我在底部添加第 6 个间隔时,代码突然无法编译并出现错误:“对成员 'buildBlock()' 的模糊引用”。
是什么导致了这个错误?这是与 SwiftUI 相关的错误吗?或者它是一个功能?这不是我第一次注意到 VStack 或 HStack 的条目数量有限,是否有一些关于此的文档?
不完全是鼓舞人心的信心,我应该切换回 UIKit 吗?
SwiftUI 用于ViewBuilder
构建构成许多 SwiftUI 视图的视图,例如VStack
、HStack
、List
等。如果您查看ViewBuilder文档,您会发现该buildBlock
函数有许多副本,每个副本都有不同数量的视图作为参数。视图数量最多的功能只接受 10 个视图,这就是为什么您会看到您观察到的限制。解决此问题的一种方法是使用Group
s:
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 个彼此非常相似的视图,建议使用类似 a 的东西,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
在原始视图中使用两个 s,但在更复杂的情况下,这一点仍然成立。例如,在具有许多元素的表单中(例如,在工作申请表中:名字、姓氏、地址、电话号码文本字段、教育下拉菜单、日期字段等),您仍然可以将一个视图拆分为更小的组件(在工作申请示例中 - 个人信息视图、教育信息视图等)。
您的VStack
(and ZStack
, HStack
, 等等) 中最多可以有 10 个孩子。这与它们的实现以及@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
}
}
}
}
在我的视图周围添加组后,我有 6 个视图,我仍然在调用错误中收到 Extra 参数。
所以这就是我为修复错误所做的。
struct ContentView: View {
var body: some View {
VStack {
Group {
//3 views here
}
Group {
//3 views here
}
}
}
}