从 SwiftUI 函数返回填充的 VStack

Posted

技术标签:

【中文标题】从 SwiftUI 函数返回填充的 VStack【英文标题】:Returning a populated VStack from a SwiftUI function 【发布时间】:2020-01-09 10:57:08 【问题描述】:

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

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

这不编译,我得到错误

函数声明了一个不透明的返回类型,但其主体中的返回语句没有匹配的底层类型

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

【问题讨论】:

【参考方案1】:

使用类型擦除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")
    )

【讨论】:

【参考方案2】:

实际上,您已经接近解决方案。实际上,您可以通过这种方式使用some View 作为返回类型:

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

【讨论】:

感觉这可以说是比公认的答案更好的解决方案,尽管它们都很相似。避免必须将 if-else 内容的每个分支都包装在 AnyView 中——减少视觉噪音和将来更改的代码【参考方案3】:

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

您应该使用自定义视图构建器实现自定义视图,以便可以返回不同的类型。此外,您可能希望从返回值中删除 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

【讨论】:

以上是关于从 SwiftUI 函数返回填充的 VStack的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI:VStack中的VStack,标签被截断

在 ScrollView 中使用 GeometryReader 的 SwiftUI 布局

从 json 填充选择器,SwiftUI

如何从 Mac OS 中的 SwiftUI 列表中删除底部/顶部项目填充

SwiftUI:在带有 Spacers 的 VStack 中平均分配多个 VStack

SwiftUI 从 ViewModel 预填充 TextField