swift - 扩展协议(protocol)属性以在 Swift 中提供默认实现

标签 swift protocols

我有一个用于多个枚举的协议(protocol),其中包括 Swift 4.2 的 CaseIterable

    public protocol CycleValue: CaseIterable {

  /// Computed property that returns the next value of the property.
  var nextValue:Self { get }
}

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)!
  }
}

我还有其他用例;例如,按钮类型。 CaseIterable 使 nextValue 的实现变得容易,但对所有类型的 CycleValue 都是一样的。

我想实现 CycleValue 的扩展,为 nextValue 属性提供默认实现并避免重复代码(即:DRY!)。

我一直在与 PAT(协议(protocol)关联类型)作斗争。似乎无法获得正确的语法。

应该可以吧?我如何为 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]
    }
}

(请注意,两种强制解包都是安全的!) 示例:

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

协议(protocol)必须符合 Equatable 才能编译,但是 不是真正的限制:CaseIterable 协议(protocol)不能有 关联值,以便编译器始终可以综合 Equatable 一致性。

关于swift - 扩展协议(protocol)属性以在 Swift 中提供默认实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52459906/

相关文章:

ios - 使用 SwiftyJson 从锁匠那里提取值(value)

ios - 如何使用 - swift - SpriteKit 编写将在特定时间运行函数的协议(protocol)

java - 如何使用 Swift (iOS) 执行以下架构。添加了 Java 代码示例

swift - 如何键入通用协议(protocol)以便能够将它们用作返回类型

ios - 在 Swift 中设置 UITabBarController 的 View Controller

ios - UIScrollView 和可变文本大小

swift - 如何在 mac os x 应用程序中通过 shell 命令访问文件?

pointers - Swift 使用 UnsafePointer<String> 从 UnsafeMutablePointer<Void> 获取值

http - 为什么不使用其余的 HTTP 动词?

javascript - 我如何编码/解码这个专有校验和(Athena 16C PID Controller )?