从 SwiftUI 函数返回填充的 VStack



我想从函数、文本或文本和按钮的 VStack 返回不同的视图。这是我的尝试之一:

func buildResponseText2() -> some View {
if (userData.success) {
return VStack {
Text("Well Done")
Button("Play Again", action: {self.userData.reset()})
}
}
return VStack {
Text("Unlucky")
}
}

这不编译,我收到错误

函数声明不透明的返回类型,但其主体中的 return 语句没有匹配的基础类型

有没有办法返回像VStack这样具有异构内容的视图容器?

使用类型擦除AnyView作为返回类型,如下所示

func buildResponseText2() -> AnyView {
if (userData.success) {
return AnyView(VStack {
Text("Well Done")
Button("Play Again", action: {self.userData.reset()})
})
}
return AnyView(VStack {
Text("Unlucky")
})
}

实际上,您已经接近解决方案了。实际上,您可以将该方法标记为ViewBuilder,并通过以下方式使用some View作为返回类型:

@ViewBuilder
func buildResponseText2() -> some View {
if userData.success {
VStack {
Text("Well Done")
Button("Play Again", action: {self.userData.reset()})
}
} else {
Text("Unlucky")
}
}

如果您愿意,还可以以相同的方式使用计算属性:

@ViewBuilder
var responseText2: some View {
if userData.success {
VStack {
Text("Well Done")
Button("Play Again", action: {self.userData.reset()})
}
} else {
Text("Unlucky")
}
}

提取布局并保留原始类型:

应使用自定义视图生成器实现自定义视图,以便可以返回不同的类型。此外,您可能希望从返回值中删除VStack,以便以后可以决定使用其他布局,而无需更改内容。

所以实现这个:

struct StackContent: View {
let success: Bool
@ViewBuilder var body: some View {
switch success {
case true:
Text("Well Done")
Button("Play Again") { print("clicked") }
case false:
Text("Unlucky")
}
}
}

然后你可以有这个:

func buildResponseText2() -> some View {
VStak { // <- you can change it to other layout containers
StackContent(success: userData.success)
}
}

也许您根本不需要该功能了;)

请注意,没有必要从 Swift 5.3 (Xcode 12( 编写@ViewBuilder

最新更新