Swift bitmask,如何知道一个int是否包含在一个bitmask中?

1rhkuytd  于 2023-06-21  发布在  Swift
关注(0)|答案(2)|浏览(72)

我需要了解如何知道一个bitmask值是否有一个来自我的API的OptionSet值。我的OptionSet是这样的:

struct RecordsObjectivesStates: OptionSet {
    var rawValue: Int
    init(rawValue: Int) {self.rawValue = rawValue}
    static let None                             = RecordsObjectivesStates(rawValue: 1 << 0)
    static let RecordRedeemed                   = RecordsObjectivesStates(rawValue: 1 << 1)
    static let RewardUnavailable                = RecordsObjectivesStates(rawValue: 1 << 2)
    static let ObjectiveNotCompleted            = RecordsObjectivesStates(rawValue: 1 << 4)
    static let Obscured                         = RecordsObjectivesStates(rawValue: 1 << 8)
    static let Invisible                        = RecordsObjectivesStates(rawValue: 1 << 16)
    static let EntitlementUnowned               = RecordsObjectivesStates(rawValue: 1 << 32)
    static let CanEquipTitle                    = RecordsObjectivesStates(rawValue: 1 << 64)
}

我有一个来自API的响应值“20”。ObjectiveNotCompleted+Invisible。我想知道Invisible是否在我的“20”值中(很明显,是吗)。
我找到了很多关于十六进制值或二进制值的解释,但没有关于Int值的解释。有人能帮我吗

xqkwcwgp

xqkwcwgp1#

您指出值20显然包含值invisible。但这是不正确的。您已将invisible定义为1 << 16。是65536。值20肯定不包含65536。
所以你首先需要修复你的OptionSet。还应该以小写字母开头命名常量。

struct RecordsObjectivesStates: OptionSet {
    var rawValue: Int

    init(rawValue: Int) {
        self.rawValue = rawValue
    }

    static let recordRedeemed        = RecordsObjectivesStates(rawValue: 1 << 0) // 1
    static let rewardUnavailable     = RecordsObjectivesStates(rawValue: 1 << 1) // 2
    static let objectiveNotCompleted = RecordsObjectivesStates(rawValue: 1 << 2) // 4
    static let obscured              = RecordsObjectivesStates(rawValue: 1 << 3) // 8
    static let invisible             = RecordsObjectivesStates(rawValue: 1 << 4) // 16
    static let entitlementUnowned    = RecordsObjectivesStates(rawValue: 1 << 5) // 32
    static let canEquipTitle         = RecordsObjectivesStates(rawValue: 1 << 6) // 64
}

现在有了这些更改(注意删除了None),常量就有了正确的值。现在值20实际上包含invisible(16)。

let states = RecordsObjectivesStates(rawValue: 20)

if states.contains(.invisible) {
    // do stuff
}

您不需要none值,因为它很容易由空选项集表示,这是您使用原始值0得到的。

rjee0c15

rjee0c152#

正如Geoff所指出的,<< n的意思是“左移n”,这提供了一种定义2的幂的简单方法。你很少会以2的幂移动。所以正确的定义应该是:

struct RecordsObjectivesStates: OptionSet {
    var rawValue: Int
    static let recordRedeemed        = RecordsObjectivesStates(rawValue: 1 << 0)
    static let rewardUnavailable     = RecordsObjectivesStates(rawValue: 1 << 1)
    static let objectiveNotCompleted = RecordsObjectivesStates(rawValue: 1 << 2)
    static let obscured              = RecordsObjectivesStates(rawValue: 1 << 3)
    static let invisible             = RecordsObjectivesStates(rawValue: 1 << 4)
    static let entitlementUnowned    = RecordsObjectivesStates(rawValue: 1 << 5)
    static let canEquipTitle         = RecordsObjectivesStates(rawValue: 1 << 6)

    // Generally shouldn't do this, but for demonstration
    static let none: RecordsObjectivesStates = []
}

我提供了.none,因为你这样做了,但通常你不会。你只需要用[]来表示它。一般来说这样更清楚。
这样,你就可以创建一个值为20:

let value = RecordsObjectivesStates(rawValue: 20)

然后检查它是否包含.contains的特定值:

value.contains(.invisible)

通常不应该定义.none的一个原因是,它允许像value.contain(.none)这样的代码,这总是正确的,因为每个集合都包含空集。这是令人困惑的,但有时人们仍然发现拥有常量是有用的。

相关问题