SwiftUI,将视图作为参数传递给@Viewbuilder

6

我很好奇能否将View类型作为参数传递给@ViewBuilder。在@ViewBuilder中传递模型/基本类型作为参数是完全有效的。

如下所示的代码:

struct TestView<Content: View>: View {
    
    let content: (String) -> Content
    
    init(@ViewBuilder content: @escaping (String) -> Content) {
        self.content = content
    }
    
    var body: some View {
        content("Some text")
    }
}

struct ContentTestView: View {
    
    var body: some View {
        TestView {
            Text("\($0)")
        }
    }
}

在以下代码中,将String替换为:
let content: (String) -> Content

如果我尝试传递一个SwiftUI的View类型,那么编译器就不会满意。

let content: (View) -> Content

尽管 @ViewBuilder 中的参数接受自定义协议类型,比如Searchable,但不接受 View 协议。
编译器会提示我:Protocol 'View' can only be used as a generic constraint because it has Self or associated type requirements 我的整个想法是让 content 可以容纳其中的 Section/List/Text
编辑:我期望的代码如下。
struct TestView<Content: View>: View {

    let content: (View) -> Content

    init(@ViewBuilder content: @escaping (View) -> Content) {
        self.content = content
    }

    var body: some View {
        content(
            List {
                ForEach(0..<10) { i in
                    Text(\(i))
                }
            }
        )
    }
}

struct ContentTestView: View {

    var body: some View {
        TestView { viewbody -> _ in
            
            Section(header: Text("Header goes here")) {
                viewbody
            }
        }
    }
}

有没有办法可以实现这个?


非常有趣...在继续之前...你希望如何在 TestView { ??? in 中使用它,因为对于你来说,??? 将是一个不透明的未知视图? - Asperi
@Asperi 更新了预期的代码。 - Nasir
1个回答

4
可能的解决方案是使用AnyView,例如:
struct TestView<Content: View>: View {
    
    let content: (AnyView) -> Content
    
    init(@ViewBuilder content: @escaping (AnyView) -> Content) {
        self.content = content
    }
    
    var body: some View {
        content(AnyView(
            Text("Demo")   // << put here any view hierarchy
        ))
    }
}

2
谢谢你的回答,它按预期工作。不建议使用AnyView(在某些情况下允许)。我在考虑是否有更好的方法。 - Nasir

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接