首页 > 解决方案 > 如何计算 SwiftUI 中的 @ViewBuilder 视图?

问题描述

我想知道如何inPutView在这个代码示例中计算我的数量,代码是这样工作的,它需要一些视图并给出背景颜色并计算视图计数,感谢您的帮助。

在此处输入图像描述

struct ContentView: View {
    var body: some View {
        
        ModelView(inputView: {
            Text("Hello, world!").padding()
            Text("Hello, world!").padding()
        })
        
    }
}

struct ModelView<Content: View>: View {
    
    var inPutView: () -> Content
    
    init(@ViewBuilder inputView: @escaping () -> Content) { self.inPutView = inputView }
    
    var body: some View {
        
        VStack {
            inPutView()
        }
        .background(Color.green)
        
        Text("count of inPutViews: 2").padding() // Here: How can I found out the count of inPutView?
        
    }
}

更新:

    struct ContentView: View {
    
    var inputViews: [AnyView] = [AnyView(Text("Hello, world!").padding()), AnyView(Text("Hello, world!").padding())]
    
    var body: some View {
        
        ModelView2(inputViews: inputViews)
        
    }
}

    struct ModelView2: View {
    var inputViews: [AnyView]

    var body: some View {
        VStack {
            ForEach(inputViews.indices, id:\.self) { index in
                inputViews[index]
            }
        }
        .background(Color.green)

        Text("count of inPutViews: \(inputViews.count)")
            .padding()
    }
}

标签: swiftswiftui

解决方案


@ViewBuilder如果闭包中的单个视图,则无法检测计数。@ViewBuilder创建一个结果视图,您将被inPutView视为单个视图。

一种可能的解决方案是将[AnyView]数组作为 的输入传递ModelView。但是 thenAnyView不符合Hashablenor Identifiable,所以你不能在 a 中使用它ForEach

在您的情况下,您可以创建一个单独的结构,符合Identifiable

struct AnyViewItem: Identifiable {
    let id = UUID()
    let view: AnyView
}

并填充ModelView数组AnyViewItem

struct ModelView: View {
    var inputViews: [AnyViewItem]

    var body: some View {
        VStack {
            ForEach(inputViews) {
                $0.view
            }
        }
        .background(Color.green)

        Text("count of inPutViews: \(inputViews.count)")
            .padding()
    }
}

然后,您可以像这样在主视图中使用它:

struct ContentView: View {
    var body: some View {
        ModelView(
            inputViews: [
                Text("Hello, world!").padding(),
                Text("Hello, world!").padding(),
            ]
            .map {
                AnyViewItem(view: AnyView($0))
            }
        )
    }
}

或者,正如评论中所建议的那样,在这种情况下,您可以创建inputViews一个[AnyView]数组并遍历其indices

ForEach(inputViews.indices, id: \.self) {
    inputViews[$0]
}

推荐阅读