SwiftUI如何动态添加VStack,HStack和List的元素?

时间:2020-04-22 10:25:56

标签: swiftui

以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个矩形。到目前为止,似乎没有问题:  Canvas

但是我添加了另一个矩形,然后报告了一个错误:通话中有额外的参数

    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仅包含10个元素的限制,因此我编写了一个函数,可以根据用户输入动态增加Rectangles的总数:

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 !!! 报告错误: 函数声明了一个不透明的返回类型,但是其主体中的return语句没有匹配的基础类型

有人知道解决方案吗?

1 个答案:

答案 0 :(得分:1)

在这种情况下,最简单的方法就是使用类型擦除,如下所示(已通过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)
}