【问题标题】:Returning a populated VStack from a SwiftUI function从 SwiftUI 函数返回填充的 VStack
【发布时间】: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 这样具有异构内容的视图容器?

【问题讨论】:

    标签: swiftui


    【解决方案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

      【讨论】:

        猜你喜欢
        • 2021-10-29
        • 1970-01-01
        • 2020-09-21
        • 2019-10-22
        • 2020-04-24
        • 1970-01-01
        • 1970-01-01
        • 2019-07-23
        • 1970-01-01
        相关资源
        最近更新 更多