swift 错误:类型“any View”不能符合“View”

m4pnthwp  于 5个月前  发布在  Swift
关注(0)|答案(1)|浏览(89)

我似乎无法理解这个问题,尝试了所有方法,都没有效果。我有一堆结构体,每个结构体都有它的视图结构体,它们也与枚举相关联。想法是有一个帮助函数,可以通过选择枚举返回结构体,它可以工作,但不适用于视图:

// Protocol that all structs conform to
protocol MyStructProtocol {
  associatedtype Body: View 
  func getView() -> Body 
  func myCustomFunc() -> String
}

// Enum for different structs
public enum MyStructs {
  case MyStruct1
  // More cases
}

struct MyStruct1: MyStructProtocol {
  func getView() -> MyStruct1View {
    return MyStruct1View()
  }
   
  func myCustomFunc() -> String {
    return "MyStruct1"
  }
}

// View for MyStruct1 
struct MyStruct1View: View {
  var body: some View {
    Text("MyStruct1 View")
  }
}

// MyStruct2 etc..

// Helper function to get struct based on enum value
func getStruct(for enumValue: MyStructs) -> any MyStructProtocol {
  switch enumValue {
  case .MyStruct1:
    return MyStruct1()
  // other cases
  }
}

// Usage in SwiftUI
struct TestView: View {
  let selectedEnum = MyStructs.MyStruct1
   
  var body: some View {
    let selectedStruct = getStruct(for: selectedEnum)
    return selectedStruct.getView() // ERROR: Type 'any View' cannot conform to 'View'
  }
}

字符串
它只工作,如果我 Package 在AnyView视图,但我听说这是一件坏事,所以寻找更好的解决方案。

zphenhs4

zphenhs41#

但我听说[AnyView是]一件坏事,所以寻找更好的解决方案。
SwiftUI的目标是在编译时解析整个View层次结构。AnyView是一个糟糕的解决方案的原因是它不能做到这一点。此外,任何其他用于避免在编译时解析整个View层次结构的技术都同样糟糕。
这类问题的典型解决方案是@ViewBuilder。它可以很容易地将switch语句转换为some View。要使用它,请将getStruct替换为getView

// Helper function to get View based on enum value
@ViewBuilder
func getView(for enumValue: MyStructs) -> some View {
    switch enumValue {
    case .MyStruct1:
        MyStruct1().getView()
        // other cases
    }
}

字符串
然后你可以使用它:

var body: some View {
        getView(for: selectedEnum)
    }


我相信您会发现使用这种方法可能不需要MyStructProtocol
也就是说,我可能会考虑这样做:

public enum MyStructs {
    case MyStruct1
    // More cases

    @ViewBuilder
    var view: some View {
        switch self {
        case .MyStruct1: MyStruct1View()
        }
    }
}

struct TestView: View {
    let selectedEnum = MyStructs.MyStruct1

    var body: some View {
        selectedEnum.view
    }
}

相关问题