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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16166895/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 06:09:15  来源:igfitidea点击:

Declaring and checking/comparing (bitmask-)enums in Objective-C

objective-cccocoaenumsbitmask

提问by thibaultcha

You know in Cocoa there is this thing, for example you can create a UIViewand do:

你知道在 Cocoa 中有这个东西,例如你可以创建一个UIView并执行:

view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

I have a custom UIViewwith multiple states, which I have defined in an enumlike this:

我有一个UIView具有多个状态的自定义,我定义enum如下:

enum DownloadViewStatus {
  FileNotDownloaded,
  FileDownloading,
  FileDownloaded
};

For each created subview, I set its tag: subview1.tag = FileNotDownloaded;

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

Then, I have a custom setter for the view state which does the following:

然后,我有一个用于视图状态的自定义设置器,它执行以下操作:

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

But what I am trying to do, is to allow this:

我想做的是允许:

subview1.tag = FileNotDownloaded | FileDownloaded;

So my subview1shows up in two states of my view. Currently, it doesn't show up in any of those two states since the |operator seems to add the two enum values.

所以我subview1的观点以两种状态出现。目前,它不会出现在这两种状态中的任何一种,因为|运算符似乎添加了两个枚举值。

Is there a way to do that?

有没有办法做到这一点?

回答by Regexident

Declaring Bitmasks:

声明位掩码:

Alternatively to assigning absolute values (1, 2, 4, …) you can declare bitmasks(how these are called) like this:

作为分配绝对值(1, 2, 4, ...)的替代方法,您可以像这样声明位掩码(如何调用它们):

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

or using modern ObjC's NS_OPTIONS/NS_ENUMmacros:

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

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

(see Abizern's answerfor more info on the latter)

(有关后者的更多信息,请参阅Abilern 的回答

The concept of bitmasks is to (usually) define each enum value with a single bit set.

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

Hence ORing two values does the following:

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

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

which is equivalent to:

这相当于:

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

Comparing Bitmasks:

比较位掩码:

One thing to keep in mind when checking against bitmasks:

检查位掩码时要记住的一件事:

Checking for exact equality:

检查完全相等:

Let's assume that status is initialized like this:

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

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

If you want to check if statusequalsFileNotDownloaded, you can use:

如果要检查是否status等于FileNotDownloaded,可以使用:

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

which is equivalent to:

这相当于:

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

Checking for "membership":

检查“会员”:

If you want to check if statusmerely containsFileNotDownloaded, you need to use:

如果要检查是否status包含 containsFileNotDownloaded,则需要使用:

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

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

See the subtle difference (and why your current "if"-expression is probably wrong)?

看到细微的区别(以及为什么您当前的“if”表达式可能是错误的)?

回答by Abizern

While @Regexident has provided an excellent answer - I must mention the modern Objective-C way of declaring Enumerated options with NS_OPTIONS:

虽然@Regexident 提供了一个很好的答案 - 我必须提到用以下方式声明枚举选项的现代 Objective-C 方式NS_OPTIONS

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

Further Reference:

进一步参考:

回答by Renetik

Useful function you can use for bitmask checking to improve readability.

可用于位掩码检查以提高可读性的有用函数。

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

回答by mah

enum DownloadViewStatus {
  FileNotDownloaded = 1,
  FileDownloading = 2,
  FileDowloaded = 4
};

This will let you perform bitwise OR's and AND's effectively.

这将使您有效地执行按位 OR 和 AND。