请注意,位掩码最常见的用例包括将一组特定的、有意义的布尔标志打包成单个字大小的值,并对这些标志执行测试。 Swift 在OptionSet 类型中为此提供了便利。
struct Bits: OptionSet {
let rawValue: UInt // unsigned is usually best for bitfield math
init(rawValue: UInt) { self.rawValue = rawValue }
static let one = Bits(rawValue: 0b1)
static let two = Bits(rawValue: 0b10)
static let four = Bits(rawValue: 0b100)
static let eight = Bits(rawValue: 0b1000)
}
let someBits = Bits(rawValue: 13)
// the following all return true:
someBits.contains(.four)
someBits.isDisjoint(with: .two)
someBits == [.one, .four, .eight]
someBits == [.four, .four, .eight, .one] // set algebra: order/duplicates moot
someBits == Bits(rawValue: 0b1011)
(当然,在实际使用中,您会为 OptionSet 中的每个“元素”值输入一些对您的用例有意义的值。)
OptionSet 实际上是一个单一的值(它支持集合代数本身,而不是元素类型),所以它不是一个集合——也就是说,它不提供枚举的方法它的元素。但是如果您打算使用位掩码的方式只需要设置和测试特定标志(或标志组合),那么您可能不需要枚举元素的方法。
如果您确实需要枚举元素,但还需要 OptionSet 的所有集合代数特征,您可以将 OptionSet 与位分割数学结合起来,例如在 @rmaddy's answer 中找到的数学:
extension OptionSet where RawValue == UInt { // try being more generic?
var discreteElements: [Self] {
var result = [Self]()
var bitmask = self.rawValue
var element = RawValue(1)
while bitmask > 0 && element < ~RawValue.allZeros {
if bitmask & 0b1 == 1 {
result.append(Self(rawValue: element))
}
bitmask >>= 1
element <<= 1
}
return result
}
}
someBits.discreteElements.map({$0.rawValue}) // => [1, 4, 8]