【问题标题】:How do i work in Swift 5 with protocol function parameters that use protocols with associated types (i.e. .pickerStyle())我如何在 Swift 5 中使用协议函数参数使用具有关联类型的协议(即 .pickerStyle())
【发布时间】:2021-04-04 17:19:05
【问题描述】:

我正在使用 SwiftUI,并希望根据 Picker 中的项目数设置 View 的 pickerStyle。如果项目少,SegmentedPickerStyle() 是理想的,WheelPickerStyle() 越多越好。

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

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

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

【问题讨论】:

  • pickerStyle 是一个通用方法,它接受符合PickerStyle 的具体类型(在编译时)。因此,它不能是 SegmentedPickerStyle 或 WheelPickerStyle - 它必须是其中之一。无论是哪一种,都会使编译器创建一个具体的方法,例如pickerStyle&lt;SegmentedPickerStyle&gt;.
  • 感谢 ELI5,我想我现在明白了。你也可以帮我解决一下吗?考虑过实施我自己的课程(即 DynamicPickerStyle),但我想这只是转移了问题?

标签: swift protocols associated-types


【解决方案1】:

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

因此,一个建议是创建一个视图修改器并有条件地应用选择器样式。这里的关键区别在于它返回类型为_ConditionalContent&lt;TrueContent, FalseContent&gt; 的条件视图。

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())

【讨论】:

  • 谢谢!有道理。这听起来像是一个计划。我会在周末尝试,如果我有其他问题,我会在下周通知您。
  • 花了一个多星期才回到这个项目。非常感谢这个优雅的解决方法和有见地的解释!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多