通过枚举迅速增加

Jim*_*ton 5 enums swift

我喜欢Swift允许使用枚举方法.我正在尝试使用方法,但我正在寻找一种更可扩展的方法:

enum CopyState{
    case binary, hex, both
    init(){
        self = .both
    }
    mutating func next() {
        if self == .binary{
            self = .hex
        } else if self == .hex {
            self = .both
        } else if self == .both{
            self = .binary
        }
    }
}

var state = CopyState()

state.next()
Run Code Online (Sandbox Code Playgroud)

我想基本上将枚举转换为整数,并以总模数选项的模数递增

添加或删除枚举选项很麻烦(我使用的是last()和next()方法).

Cri*_*tik 14

更新从Swift 4.2开始,您可以使用新添加的支持CaseIterable协议,该协议增加了编译器支持,以生成枚举的所有案例列表.然后你的枚举可能看起来像这样(不再是硬编码的起始值):

enum CopyState: CaseIterable {
    case binary, hex, both

    mutating func next() {
        let allCases = type(of: self).allCases
        self = allCases[(allCases.index(of: self)! + 1) % allCases.count]
    }
}
Run Code Online (Sandbox Code Playgroud)

或者,更加冗长,但更好地分离了关注点:

extension CaseIterable where Self: Equatable {
    mutating func next() {
        let allCases = Self.allCases
        // just a sanity check, as the possibility of a enum case to not be
        // present in `allCases` is quite low
        guard let selfIndex = allCases.index(of: self) else { return }
        let nextIndex = Self.allCases.index(after: selfIndex)
        self = allCases[nextIndex == allCases.endIndex ? allCases.startIndex : nextIndex]
    }
}

enum CopyState: CaseIterable {
    case binary, hex, both
}

var state = CopyState.hex
state.next()
print(state) // both
state.next()
print(state) // binary
Run Code Online (Sandbox Code Playgroud)

您可以使用CaseIterable枚举的原始值(请注意,如果您不指定它,这也是默认的原始值),并使用它如下所示:

extension Collection {
    // adding support for computing indexes in a circular fashion
    func circularIndex(after i: Index) -> Index {
        let nextIndex = index(after: i)
        return nextIndex == endIndex ? startIndex : nextIndex
    }
}

extension Collection where Element: Equatable {
    // adding support for retrieving the next element in a circular fashion
    func circularElement(after element: Element) -> Element? {
        return index(of: element).map { self[circularIndex(after: $0)] }
    }
}

// Protocol to allow iterating in place (similar to a type conforming to both Sequence and IteratorProtocol)
protocol InPlaceIterable {
    mutating func next()
}

extension InPlaceIterable where Self: CaseIterable, Self: Equatable {
    // adding default implementation for enums
    mutating func next() {
        self = type(of: self).allCases.circularElement(after: self)!
    }
}

// now the enums need only the protocol conformances, they get the
// functionalities for free
enum CopyState: CaseIterable, InPlaceIterable {
    case binary, hex, both
}
Run Code Online (Sandbox Code Playgroud)

只要您按连续顺序获得枚举案例的原始值,这样就可以正常工作.默认情况下,编译器会分配连续的原始值.

Int如果第一种情况发生变化,您还需要记住更新方法,否则它将无法正常工作.

@MartinR建议的上述限制的替代方法是强制解包原始值零:

enum CopyState: Int {
    case binary, hex, both

    mutating func next(){
        self = CopyState(rawValue: rawValue + 1) ?? .binary
    }
}

var state = CopyState.hex
state.next()
print(state) // both
state.next()
print(state) // binary
Run Code Online (Sandbox Code Playgroud)

当第一个枚举案例发生更改时,上述代码不需要更新方法,但如果枚举的起始原始值发生更改,则可能会导致应用程序崩溃.

  • 或`返回CopyState(rawValue:rawValue + 1)?CopyState(rawValue:0)!`避免对第一个枚举情况进行“硬编码”。 (2认同)