【问题标题】:How can I count @ViewBuilder Views in SwiftUI?如何计算 SwiftUI 中的 @ViewBuilder 视图?
【发布时间】:2021-04-26 20:02:34
【问题描述】:

我想知道如何在这个代码示例中计算我的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()
    }
}

【问题讨论】:

    标签: swift swiftui


    【解决方案1】:

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

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

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

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

    并使用AnyViewItem 的数组填充ModelView

    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))
                }
            )
        }
    }
    

    或者,按照 cmets 中的建议,在这种情况下,您可以将 inputViews 设为 [AnyView] 数组并遍历其 indices

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

    【讨论】:

    • 谢谢,我根据您的代码进行了更新,您能看到吗?我认为我们不需要再做一步来制作 AnyViewItem。没事吧?
    • @swiftPunk 是的,你是对的,在这种情况下你可以使用indices。我想我只是在想将来如何使用它。我会更新我的答案。
    • 不,让它留下来,它有丰富的代码供其他人使用,谢谢
    • @swiftPunk 好的,我保留了原始解决方案并添加了您的评论作为替代方案。
    猜你喜欢
    • 2020-12-28
    • 2020-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-03
    • 1970-01-01
    • 2020-06-19
    相关资源
    最近更新 更多