在NS_OPTIONS中测试多个标志或条件

baz*_*ola 2 enums if-statement bit-manipulation objective-c

这就是我想要做的.我有一个简单的NS_OPTIONS设置

typedef NS_OPTIONS(NSUInteger, BuildingsPresent) {
    NoBuildings         = 0,
    LadderPresent       = 1 << 0,
    WallPresent         = 1 << 1,
    RoomPresent         = 1 << 2,
    RoomUpgradePresent  = 1 << 3
};
Run Code Online (Sandbox Code Playgroud)

我正在设置这样的值:

self.buildingPresent |= LadderPresent | WallPresent;
Run Code Online (Sandbox Code Playgroud)

这似乎工作正常,但现在我想一次性测试if语句中的标志,如下所示:

if (self.buildingPresent & LadderPresent & WallPresent) {
Run Code Online (Sandbox Code Playgroud)

这不能正常工作.如果我将它分解为多个if语句,它似乎确实有效:

if (self.buildingPresent & LadderPresent) {
    if (self.buildingPresent & WallPresent) {
        //do something
    }
}
Run Code Online (Sandbox Code Playgroud)

我也想正确测试缺少某些东西,所以写这个的理想方式是:

if (!(self.buildingPresent & RoomPresent) && (self.buildingPresent & LadderPresent & WallPresent) {
Run Code Online (Sandbox Code Playgroud)

这在Objective-C中是否可行?难道我做错了什么?

nhg*_*rif 5

if (self.buildingPresent & LadderPresent & WallPresent)
Run Code Online (Sandbox Code Playgroud)

这将始终评估为false.

&操作仅在位的位置,其中运营商的双方在所有其他位置的位设置为1和0,则返回1.

LadderPresent & WallPresent没有两个位都是1的位置,因此它们将始终为全0.无论你&用什么零都将全部为零,因此是假的.

如果您打算检查LadderPresent位和WallPresent位是否都处于活动状态,则需要将OR这些AND结果一起放在变量上:

if (self.buildingPresent & (LadderPresent | WallPresent)) {
Run Code Online (Sandbox Code Playgroud)

这将会为任意值返回true self.buildingPresent,只要无论是LadderPresentWallPresent位设置为1.

为了验证BOTH被设置为1,我们必须AND将变量设置为一个掩码,该掩码表示两者都设置为1,然后查看该掩码是否等于我们想要的掩码:

NSInteger bitMask = (LadderPresent | WallPresent)
if ((self.buildingPresent & bitMask) == bitMask) {
Run Code Online (Sandbox Code Playgroud)

此示例现在仅在BOTH设置为1时才返回true.


测试缺少的正确方法看起来更像是这样的:

(self.buildingPresent & RoomPresent) == 0
Run Code Online (Sandbox Code Playgroud)

self.buildingPresent在该位置具有0 时返回true ,并且当其具有1时返回false.