我有一个协议,我用于几个枚举,其中包括Swift 4.2的CaseIterable
public protocol CycleValue: CaseIterable {
/// Computed property that returns the next value of the property.
var nextValue:Self { get }
}
Run Code Online (Sandbox Code Playgroud)
我的CycleValue用例之一是使用Theme属性:
@objc public enum AppThemeAttributes: CycleValue {
case classic, darkMode // etc.
public var nextValue: AppThemeAttributes {
guard self != AppThemeAttributes.allCases.last else {
return AppThemeAttributes.allCases.first!
}
return AppThemeAttributes(rawValue: self.rawValue + 1)!
}
}
Run Code Online (Sandbox Code Playgroud)
我有其他用例; 例如,按钮类型.CaseIterable使nextValue的实现变得容易,但对于所有类型的CycleValue都是一样的.
我想实现CycleValue的扩展,它为nextValue属性提供默认实现,并避免重复代码(即:DRY!).
我一直在努力使用PAT(协议相关类型).似乎无法使语法正确.
它应该是可能的,对吗?如何为nextValue提供默认实现以避免重复ode?
一种可能的解决方案是在allCases集合中定位当前值,并返回下一个元素(或环绕到第一个元素):
public protocol CycleValue: CaseIterable, Equatable {
var nextValue: Self { get }
}
public extension CycleValue {
var nextValue: Self {
var idx = Self.allCases.index(of: self)!
Self.allCases.formIndex(after: &idx)
return idx == Self.allCases.endIndex ? Self.allCases.first! : Self.allCases[idx]
}
}
Run Code Online (Sandbox Code Playgroud)
(请注意,两个强制解包都是安全的!) 示例:
public enum AppThemeAttributes: CycleValue {
case classic, darkMode // etc.
}
let a = AppThemeAttributes.classic
print(a) // classic
let b = a.nextValue
print(b) // darkMode
let c = b.nextValue
print(c) // classic
Run Code Online (Sandbox Code Playgroud)
协议必须符合Equatable此要编译,但这不是一个真正的限制:CaseIterable协议不能具有关联的值,因此编译器可以始终合成
Equatable一致性.
| 归档时间: |
|
| 查看次数: |
245 次 |
| 最近记录: |