Declaring and using a bit field enum in Swift

Pascal Bourque picture Pascal Bourque · Jun 9, 2014 · Viewed 32.4k times · Source

How should bit fields be declared and used in Swift?

Declaring an enum like this does work, but trying to OR 2 values together fails to compile:

enum MyEnum: Int
{
    case One =      0x01
    case Two =      0x02
    case Four =     0x04
    case Eight =    0x08
}

// This works as expected
let m1: MyEnum = .One

// Compiler error: "Could not find an overload for '|' that accepts the supplied arguments"
let combined: MyEnum = MyEnum.One | MyEnum.Four

I looked at how Swift imports Foundation enum types, and it does so by defining a struct that conforms to the RawOptionSet protocol:

struct NSCalendarUnit : RawOptionSet {
    init(_ value: UInt)
    var value: UInt
    static var CalendarUnitEra: NSCalendarUnit { get }
    static var CalendarUnitYear: NSCalendarUnit { get }
    // ...
}

And the RawOptionSet protocol is:

protocol RawOptionSet : LogicValue, Equatable {
    class func fromMask(raw: Self.RawType) -> Self
}

However, there is no documentation on this protocol and I can't figure out how to implement it myself. Moreover, it's not clear if this is the official Swift way of implementing bit fields or if this is only how the Objective-C bridge represents them.

Answer

Nate Cook picture Nate Cook · Jun 9, 2014

You can build a struct that conforms to the RawOptionSet protocol, and you'll be able to use it like the built-in enum type but with bitmask functionality as well. The answer here shows how: Swift NS_OPTIONS-style bitmask enumerations.