简体   繁体   中英

how to increment a swift int enumeration

I have a swift enumeration

 enum MainState : Int {
     case NotStarted
     case Init
     case AskWhatToText
     case RecordWhatToText
 }    
 var state = MainState.NotStarted

and would like to do something like

state++

but get an error. suggestions?

This is not C, where enums are integers. In swift an enum is a proper type in it's own right and you cannot perform math operations on it.

However, you can grab the raw value which is an integer, and do math on that. Then create a new enum:

var newState = MainState(rawValue: state.rawValue + 1)

Note that "newState" is an optional. You'll get null if rawValue + 1 doesn't exist in the enum.

What do you want to happen when you increment an enum? What should happen when it's on the RecordWhatToText state and you increment it again, or on the NotStarted state and you decrement it? These are questions that have more to do with your enum and less with the design of enums in general. (After all, the designer of one enum might want it to loop around, another might want it to stay at the max value, and another might want to make incrementing past the max be an error.) I'd presume that's at least part of why custom enums don't come with increment operators out of the box.

There's no saying you can't make your own operators that fit the design of how you want your enum to be used, though. This example makes attempting to increment past the maximum a no-op:

postfix func ++(inout state: MainState) {
    if let newValue = MainState(rawValue: state.rawValue + 1) {
        state = newValue
    } else {
        // leave state alone
    }
}

Note that you'll also need to make a prefix func ++ if you also want pre-increment, and you might consider making decrement operators, too.

extension CaseIterable where Self: Equatable {

    static postfix func ++(c: inout Self)  {
        let all = Self.allCases
        let idx = all.firstIndex(of: c)!
        let next = all.index(after: idx)
        c = all[next == all.endIndex ? all.startIndex : next]
    }
    
    static postfix func --(c: inout Self)  {
        let all = Self.allCases
        var idx = all.firstIndex(of: c)!
        if idx == all.startIndex {
            let lastIndex = all.index(all.endIndex, offsetBy: -1)
            c = all[lastIndex]
        } else {
            all.formIndex(&idx, offsetBy: -1)
            c = all[idx]
        }
    }
}

Usage:

enum MainState: Int, CaseIterable {
     case notStarted
     case `init`
     case askWhatToText
     case recordWhatToText
}
var state = MainState.notStarted
state++
print(state) // init
state++
print(state) // askWhatToText
state--
print(state) // init

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM