在 Objective-C 中声明和检查/比较(位掩码 -)枚举

你知道在 Cocoa 中有这样一个东西,例如,你可以创建一个 UIView,然后做:

view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

我有一个具有多个状态的自定义 UIView,我在 enum中定义了这样的状态:

enum DownloadViewStatus {
FileNotDownloaded,
FileDownloading,
FileDownloaded
};

对于每个创建的子视图,我设置它的 tag: subview1.tag = FileNotDownloaded;

然后,我为视图状态创建了一个自定义 setter,它执行以下操作:

for (UIView *subview in self.subviews) {
if (subview.tag == viewStatus)
subview.hidden = NO;
else
subview.hidden = YES;
}

我想做的事允许这样做:

subview1.tag = FileNotDownloaded | FileDownloaded;

所以我的 subview1显示在我视图的两个状态中。目前,它不显示在这两种状态中的任何一种,因为 |操作符似乎添加了两个枚举值。

有办法吗?

28753 次浏览
enum DownloadViewStatus {
FileNotDownloaded = 1,
FileDownloading = 2,
FileDowloaded = 4
};

这将使您能够有效地执行按位 OR 和 AND 操作。

声明位掩码:

或者,为绝对值赋值(124、 ...) ,可以像下面这样声明 位掩码(如何调用它们) :

typedef enum : NSUInteger {
FileNotDownloaded = (1 << 0), // => 00000001
FileDownloading   = (1 << 1), // => 00000010
FileDownloaded     = (1 << 2)  // => 00000100
} DownloadViewStatus;

或使用现代的 Objecc 的 NS_OPTIONS/NS_ENUM宏:

typedef NS_OPTIONS(NSUInteger, DownloadViewStatus) {
FileNotDownloaded = (1 << 0), // => 00000001
FileDownloading   = (1 << 1), // => 00000010
FileDownloaded    = (1 << 2)  // => 00000100
};

(有关后者的更多信息,请参见 阿比森的回答)

位掩码的概念是(通常)用一个位集定义每个枚举值。

因此,ORing 两个值执行以下操作:

DownloadViewStatus status = FileNotDownloaded | FileDownloaded; // => 00000101

相当于:

  00000001 // FileNotDownloaded
| 00000100 // FileDownloaded
----------
= 00000101 // (FileNotDownloaded | FileDownloaded)

比较位掩码:

在检查位掩码时要记住一点:

检查是否完全相等:

让我们假设 status 是这样初始化的:

DownloadViewStatus status = FileNotDownloaded | FileDownloaded; // => 00000101

如果你想检查 status 等于 FileNotDownloaded,你可以使用:

BOOL equals = (status == FileNotDownloaded); // => false

相当于:

   00000101 // (FileNotDownloaded | FileDownloaded)
== 00000100 // FileDownloaded
-----------
=  00000000 // false

查询「会员资格」 :

如果你想检查 status是否仅仅是 包含 FileNotDownloaded,你需要使用:

BOOL contains = (status & FileNotDownloaded) != 0; // => true


00000101 // (FileNotDownloaded | FileDownloaded)
&  00000100 // FileDownloaded
-----------
=  00000100 // FileDownloaded
!= 00000000 // 0
-----------
=  00000001 // 1 => true

看到细微的差别(为什么你现在的“如果”-表达式可能是错误的) ?

虽然@Regexent 提供了一个很好的答案——我必须提到使用 NS_OPTIONS声明枚举选项的现代 Objective-C 方法:

typedef NS_OPTIONS(NSUInteger, DownloadViewStatus) {
FileNotDownloaded = 0,
FileDownloading   = 1 << 0,
FileDownloaded    = 1 << 1
};

进一步参考:

有用的功能,您可以使用位掩码检查,以提高可读性。

BOOL bitmaskContains(NSUInteger bitmask, NSUInteger contains) {
return (bitmask & contains) != 0;
}