类型“任何视图”无法符合泛型协议上的“视图”

Joe*_*tto 17 generics xcode ios swift swiftui

我正在使用协议来定义对默认View协议的覆盖,以在我的应用程序中创建一些模板化视图。它们都将共享CalculationComponent大部分布局的相同视图,但随后将实现使用@ViewBuilder泛型传递的不同按钮/控件。

我遇到的问题是,在定义协议主体时,通用类型在Type 'any View' cannot conform to 'View'. <Content: View>我认为这与上面的部分有直接关系CalculationComponent

计算组件.swift

struct CalculationComponent<Content: View>: View {
    @Binding var mainCalculation: String
    @Binding var secondaryCalculation: String
    @ViewBuilder var content: () -> Content
    
    var body: some View {
        // Template UI here

        content()
    }
}

Run Code Online (Sandbox Code Playgroud)

CalculationView.swift

protocol CalculationView: View {
    var mainCalculation: String { get set }
    var secondaryCalculation: String { get set}
    var body: CalculationComponent<View> { get } // Type 'any View' cannot conform to 'View'
}
Run Code Online (Sandbox Code Playgroud)

CalculatorView.swift

struct CalculatorView: CalculationView {
    @State internal var mainCalculation: String = ""
    @State internal var secondaryCalculation: String = ""
    
    var body: CalculationComponent {
        CalculationComponent(
            mainCalculation: $mainCalculation,  
            secondaryCalculation: $secondaryCalculation
        ) {
            Text("Buttons and view content here")
        }
    }
    
}

Run Code Online (Sandbox Code Playgroud)

Swe*_*per 14

如果我理解正确的话,你想要一个专门版本的View协议,哪里Body是CalculationComponent<some View>,并且你不想some View在符合协议时明确地写出“”是什么,再加上一些其他要求。

您可以将关联类型添加到CalculationView,

protocol CalculationView: View {
    associatedtype Content: View
    
    var mainCalculation: String { get set }
    var secondaryCalculation: String { get set}
    var body: CalculationComponent<Content> { get } // Type 'any View' cannot conform to 'View'
}
Run Code Online (Sandbox Code Playgroud)

然后CalculationComponent<some View>在遵守协议时说:

struct CropFactorCalculatorView: CalculationView {
    
    @State internal var mainCalculation: String = ""
    @State internal var secondaryCalculation: String = ""
    
    var body: CalculationComponent<some View> {
        CalculationComponent(
            mainCalculation: $mainCalculation,
            secondaryCalculation: $secondaryCalculation
        ) {
            VStack {
                Text("Some Text")
                Text("Some Other Text")
            }
        }
    }
    
}
Run Code Online (Sandbox Code Playgroud)

  • 这样可行!你能解释一下为什么我不能只将“View”传递给“CalculationComponent”的泛型吗?为什么必须首先将其定义为“关联类型”? (2认同)
  • @JoeScotto 是的。“视图”不符合“视图”。 (2认同)