Swift Bitmasks - Dinge, die niemand braucht

In der Objective-C Welt kennt man Bitmasken zu genüge. Schon wenn man einen einfachen UIButton konfigurieren möchte wird man mit einem UIControlState konfrontiert. Da gibt es dann plötzlich so Dinge wie UIControlStateHighlighted|UIControlStateDisabled. Und vor den Zeiten von Autolayout musste man sich noch mit UIViewAutoresizing rumschlagen. In Swift sind Bitmasken kein existierendes Konzept und das Erstellen einer eigenen Datenstruktur dafür ist nicht trivial.

Um Bitmasken, Generics und Bitshifting in Swift ein wenig besser zu verstehen habe ich mir eine extension für UInt8 geschrieben mit der man eine acht bit große Bitmaske erstellen kann. Größere Bitmasken sind ohne weiteres möglich.

typealias Bitmask = UInt8
typealias BitName = UInt8

extension Bitmask {
    func setBit<T: RawRepresentable where T.RawValue == BitName>(index: T, newValue: Bool) -> Bitmask {
        let rawValue = index.rawValue
        let currentState: Bool = getBit(index)
        if currentState != newValue {
            return self ^ (1 << rawValue)
        }
        return self
    }
    
    func getBit<T: RawRepresentable where T.RawValue == BitName>(index: T) -> Bool {
        let rawValue = index.rawValue
        return self & (1 << rawValue) > 0
    }
    
    var description: String {
        return "[\((self>>7)%2),\((self>>6)%2),\((self>>5)%2),\((self>>4)%2),\((self>>3)%2),\((self>>2)%2),\((self>>1)%2),\(self%2)]"
    }
}

Mit einer Beispielhaften Nutzung.

enum RoomBitNames: BitName {
    case Livingroom = 0
    case Kitchen = 1
    case Bedroom = 2
    // there can be 5 more bits
}


let a: Bitmask = 0
let b = a.setBit(RoomBitNames.Livingroom, newValue: true)
let c = b.setBit(RoomBitNames.Kitchen, newValue: true)
let hasLivingroom = c.getBit(RoomBitNames.Livingroom)
let hasKitchen = c.getBit(RoomBitNames.Kitchen)
let hasBedroom = c.getBit(RoomBitNames.Bedroom)
print(a.description)
print(b.description)
print(c.description)