SwiftUI如何动态添加VStack、HStack和List元素



以VStack为例:

VStack {
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
}

我在VStack中添加了10个矩形。到目前为止似乎没有问题:画布

然而,我添加了另一个矩形,然后报告了一个错误:调用时有额外的参数

VStack {
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
}

这意味着VStack、HStack和List的构造函数只能接受10个参数,所以我改变了策略,使用嵌套的VStack:

VStack {
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
VStack {
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
}
}

这可以突破VStack只能有十个元素的限制,所以我写了一个函数来根据用户输入动态增加矩形的总数:

private func createRectangles(rectCount: UInt) -> some View {
func createRectangles(_ i: UInt) -> some View {
if i <= rectCount {
return VStack {
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
createRectangles(i + 1)
}
} else {
return VStack {
Rectangle()
}
}
}
return createRectangles(1)
}

Opos!!!报告错误:函数声明了一个不透明的返回类型,但其主体中的返回语句没有匹配的底层类型

有人知道解决办法吗?

在这种情况下,最简单的方法就是使用类型擦除,如下所示(使用Xcode 11.4/iOS 13.4测试(

private func createRectangles(rectCount: UInt) -> some View {
func createRectangles(_ i: UInt) -> some View {
if i <= rectCount {
return AnyView(VStack {
Rectangle().size(CGSize(width: 20, height: 20)).fill(Color.green).frame(width: 20, height: 20)
createRectangles(i + 1)
})
} else {
return AnyView(VStack {
Rectangle()
})
}
}
return createRectangles(1)
}

最新更新