英文:
Using Views as parameters for another View without AnyView
问题
View1
结构体 View1: View {
    let title: String
    let text: String
    var body: some View {
        HStack {
            Text(title)
            Text(text).bold()
        }
    }
}
View2
结构体 View2: View {
    let title: String
    let text: String
    var body: some View {
        HStack {
            Text(title).bold()
            Text(text)
        }
    }
}
ParameterView - 目前传递的 view 参数被包装在 AnyView() 中。
结构体 ParameterView: View {
    let title: String
    let view: any View
    var body: some View {
        HStack {
            Text(title)
            AnyView(view)
        }
    }
}
In practice:
结构体 ParameterView_Previews: PreviewProvider {
    static var previews: some View {
        VStack {
            ParameterView(
                title: "Noodles",
                view: View1(title: "£", text: "1.00")
            ) // Noodles £ 1.00
            ParameterView(
                title: "Mass",
                view: View2(title: "100", text: "g")
            ) // Mass 100 g
        }
    }
}
英文:
I have two views that I want to use as possible parameters in another view. I've been using AnyView, but would much rather use @ViewBuilder instead; I'm not 100% sure on how to implement this though.
See below:
View1
struct View1: View {
    let title: String
    let text: String
    var body: some View {
        HStack {
            Text(title)
            Text(text).bold()
        }
    }
}
View 2
struct View2: View {
    let title: String
    let text: String
    var body: some View {
        HStack {
            Text(title).bold()
            Text(text)
        }
    }
}
ParameterView - currently the view parameter being passed through is being wrapped in AnyView().
struct ParameterView: View {
    let title: String
    let view: any View
    var body: some View {
        HStack {
            Text(title)
            AnyView(view)
        }
    }
}
In practice:
struct ParameterView_Previews: PreviewProvider {
    static var previews: some View {
        VStack {
            ParameterView(
                title: "Noodles",
                view: View1(title: "£", text: "1.00")
            ) // Noodles £ 1.00
            ParameterView(
                title: "Mass",
                view: View2(title: "100", text: "g")
            ) // Mass 100 g
        }
    }
}
答案1
得分: 1
你沿着正确的方向 - 使用 @ViewBuilder 是正确的方法!我们将与泛型一起使用它。我将以你的 ParameterView 为例:
struct ParameterView<Content: View>: View {
    let title: String
    @ViewBuilder let view: Content
    var body: some View {
        HStack {
            Text(title)
            view
        }
    }
}
在这里,我们创建了一个视图,它使用泛型类型 Content,它必须符合 View。我们使用 @ViewBuilder 属性包装器,它基本上表示我们的属性 view 是一个将返回类型为 Content 的属性的函数,并且因为 Content: View,所以我们可以像对待任何 View 一样使用这个属性。然后,剩下的就是在 body 中使用它。
这是用法:
struct UsageView: View {
    var body: some View {
        ParameterView(title: "Noodles") {
            View1(title: "£", text: "1.00")
        }
    }
}
请注意,我在这里使用了尾随闭包语法,因为 @ViewBuilder 将我们的属性转换为方法。
英文:
You're along the right lines - using @ViewBuilder is the way to go! We will combine this with the use of generics. I'll use your ParameterView as an example:
struct ParameterView<Content: View>: View {
    let title: String
    @ViewBuilder let view: Content
    var body: some View {
        HStack {
            Text(title)
            view
        }
    }
}
Here we're creating a view that uses a generic type Content that must conform to View. We use the @ViewBuilder property wrapper that basically says our property view is some function that will return a property of type Content and because Content: View we can use this property as we can with any View. Then all that's left to do is use that within the body.
Here's the usage:
struct UsageView: View {
    var body: some View {
        ParameterView(title: "Noodles") {
            View1(title: "£", text: "1.00")
        }
    }
}
Note that I'm using trailing closure syntax here because @ViewBuilder turns our property into a method.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论