我如何在 Swift 5 中使用协议功能参数工作,这些参数使用具有关联类型的协议(即 .pickerStyle())

How do i work in Swift 5 with protocol function parameters that use protocols with associated types (i.e. .pickerStyle())

我正在使用 SwiftUI 并想根据选择器中的项目数设置视图的 pickerStyle。对于一些项目,SegmentedPickerStyle() 是理想的,更多的 WheelPickerStyle() 更好。

}.pickerStyle(productsObserver.product.productFamilies?.count ?? 0 < 5 ? SegmentedPickerStyle() : WheelPickerStyle())

函数签名如下: func pickerStyle<S>(_ style: S) -> some View where S : PickerStyle 我了解到在函数签名中使用泛型,因为 PickerStyle 使用关联类型。

它不应该是一个如此困难的问题而且可能不是 - 协议应该像这样简单地工作=,但我看不到它。 非常感谢任何帮助!

pickerStyle 是一种泛型方法,它接受符合 PickerStyle 的具体类型(在编译时)。因此,它不能是 SegmentedPickerStyleWheelPickerStyle(在 运行 时确定) - 它必须是其中之一。

因此,一个建议是创建一个视图修饰符并有条件地应用选择器样式。这里的关键区别在于它 returns 类型为 _ConditionalContent<TrueContent, FalseContent>.

的条件视图
struct PickerStyleOption<P1: PickerStyle, P2: PickerStyle>: ViewModifier {
    let predicate: () -> Bool
    let style1: P1
    let style2: P2
    
    @ViewBuilder
    func body(content: Content) -> some View {
        if predicate() {
            content
                .pickerStyle(style1)
        } else {
            content
                .pickerStyle(style2)
        }
    }
}

为方便起见,您可以创建一个扩展:

extension View {
    func pickerStyleOption<P1: PickerStyle, P2: PickerStyle>(
            _ condition: @autoclosure @escaping () -> Bool,
            then style1: P1, 
            else style2: P2) -> some View {

        self.modifier(
            PickerStyleOption(predicate: condition, style1: style1, style2: style2)
        )
    }
}

并像这样使用它:

Picker(...) {
   ...
}
.pickerStyleOption((productsObserver.product.productFamilies?.count ?? 0) < 5, 
   then: SegmentedPickerStyle(), else: WheelPickerStyle())