英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论