今天我尝试在Playground玩BitSet,我注意到这个模式
struct Activities: OptionSet {
let rawValue: Int
static let eating = Activities(rawValue: 1)
static let programming = Activities(rawValue: 2)
static let breathing = Activities(rawValue: 3)
static let saveGotham = Activities(rawValue: 4)
}
let act: Activities = [.eating, .programming, .saveGotham]
act.contains(.breathing). //true /* this is unexpected */
act.contains(.saveGotham) //true
虽然,阵列中没有包含值' .breathing'它仍然是真的。 我用不同的rawValue
修改了相同的结构 struct Activities: OptionSet {
let rawValue: Int
static let eating = Activities(rawValue: 1)
static let programming = Activities(rawValue: 8)
static let breathing = Activities(rawValue: 16)
static let saveGotham = Activities(rawValue: 32)
}
let act: Activities = [.eating, .programming, .saveGotham]
act.contains(.breathing). //false
act.contains(.saveGotham) //true
并获得所需的输出。如果有人能够解决这个问题并解释“选择套件”如何解决问题,那就太棒了。实际上是有效的。
谢谢。
答案 0 :(得分:2)
...表示位集类型,其中各个位表示集合的成员。
在你的情况下,
let act: Activities = [.eating, .programming, .saveGotham]
print(act.rawValue) // 7
存储为包含原始值的BITWISE OR的整数
(1 | 2 | 4 = 7)
和
act.contains(.breathing). //true /* this is unexpected */
测试BITWISE和7 & 3
是否为非零(这种情况)。
因此,你不应该使用连续的原始值,而应该使用 两个,即每个互斥值由一个表示 位位置:
struct Activities: OptionSet {
let rawValue: Int
static let eating = Activities(rawValue: 1)
static let programming = Activities(rawValue: 2)
static let breathing = Activities(rawValue: 4)
static let saveGotham = Activities(rawValue: 8)
}
或等效地:
struct Activities: OptionSet {
let rawValue: Int
static let eating = Activities(rawValue: 1 << 0)
static let programming = Activities(rawValue: 1 << 1)
static let breathing = Activities(rawValue: 1 << 2)
static let saveGotham = Activities(rawValue: 1 << 3)
}
现在一切都按预期工作:
let act: Activities = [.eating, .programming, .saveGotham]
print(act.rawValue) // 11
print(act.contains(.breathing)) // false
print(act.contains(.saveGotham)) // true
答案 1 :(得分:1)
从OptionSet的文档页面
您使用OptionSet协议来表示位集类型,其中 各个位代表一组的成员。采用这个协议 您的自定义类型允许您执行与集相关的操作,例如 这些类型的成员资格测试,工会和交叉点。什么是 更多,当使用特定标准实施时,采用此方法 协议不需要你做额外的工作。
创建选项集时,请在类型中包含rawValue属性 宣言。 rawValue属性必须是符合的类型 FixedWidthInteger协议,例如Int或UInt8。接下来,创建 使用唯一的自定义类型的静态属性的唯一选项 每个人的权力为2(1,2,4,8,16等) property的原始值,以便每个属性可以用a表示 单个类型的原始值。
rawValue应该是位设置类型。那么,上面的代码发生了什么,
让行为:活动= [.eating,.programming,.saveGotham]
因为吃1是相当于00000001,编程是2,即00000010,saveGotham是4,即00000100.所以,你的act变量现在将所有三位设置在最后,这可以表示为00000111。
00000111现在还包括呼吸。
从上面的注释中,您应该将原始值按位排列。
你可以从文档中拿一个例子,
struct ShippingOptions: OptionSet {
let rawValue: Int
static let nextDay = ShippingOptions(rawValue: 1 << 0)
static let secondDay = ShippingOptions(rawValue: 1 << 1)
static let priority = ShippingOptions(rawValue: 1 << 2)
static let standard = ShippingOptions(rawValue: 1 << 3)
static let express: ShippingOptions = [.nextDay, .secondDay]
static let all: ShippingOptions = [.express, .priority, .standard]
}