swiftoptionsettype

Swift 3.0 OptionSet Bit Test


With the following OptionSet:

struct StatusOptions : OptionSet {
    let rawValue: Int
    static let CountdownDuration0 = StatusOptions(rawValue: 1 << 0)
    static let CountdownDuration1 = StatusOptions(rawValue: 1 << 1)
    static let CountdownDuration2 = StatusOptions(rawValue: 1 << 2)
    static let CountdownDuration3 = StatusOptions(rawValue: 1 << 3)
    static let CountdownDuration4 = StatusOptions(rawValue: 1 << 4)
    static let CountdownDuration5 = StatusOptions(rawValue: 1 << 5)
    static let HomeMode = StatusOptions(rawValue: 1 << 6)
    static let AwayMode = StatusOptions(rawValue: 1 << 7)

    static let Disarmed: StatusOptions = []
    static let ArmedHome: StatusOptions = .HomeMode
    static let ArmedAway: StatusOptions = .AwayMode
    static let ArmedBoth: StatusOptions = [.HomeMode, .AwayMode]
    static let ArmingCountdown: StatusOptions = [.CountdownDuration0, .CountdownDuration1, .CountdownDuration2, .CountdownDuration3, .CountdownDuration4, .CountdownDuration5]
}

How do I compare a byte

var statusFlags: UInt8 = 0b00000000

To the Options?

The following is what I'd think would work, but causes a playground error:

if (statusFlags & .Disarmed) {
    print("Disarmed")
}

Thanks


Solution

  • Since .Disarmed is zero, you say:

    if statusFlags == .Disarmed
    

    or even more simply:

    if statusFlags.isEmpty
    

    For other values, you say, e.g.:

    if statusFlags.contains(.CountdownDuration3)
    

    That is the whole point of an OptionSet. You use set operations, not arithmetic bit operations.

    But for this to work, so that you can take advantage of OptionSet's yummy goodness, statusFlags needs to be a StatusOptions. You can do that by way of the StatusOptions rawValue: initializer:

    let statusFlags = StatusOptions(rawValue:0b00000000)
    statusFlags.isEmpty // true
    

    (Note that in Swift 3, a zero bitmask like .Disarmed probably wouldn't even be used. Zero is just an empty set.)