在Objective-C中声明和检查/比较(bitmask-)枚举 [英] Declaring and checking/comparing (bitmask-)enums in Objective-C

查看:196
本文介绍了在Objective-C中声明和检查/比较(bitmask-)枚举的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



<$ p

$ p> view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

我有一个具有多个状态的自定义 UIView ,我在一个枚举中定义,如下所示:

 枚举DownloadViewStatus {
FileNotDownloaded,
FileDownloading,
FileDownloaded
};

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



然后,我有一个自定义设置器的视图状态,以下:

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

但是,我想要做什么允许:

  subview1.tag = FileNotDownloaded | FileDownloaded; 

所以我的 subview1 显示在两个状态我的看法目前,由于 | 运算符似乎添加了两个枚举值,所以它们不显示在这两个状态中的任何一个中。



有没有办法这样做?

解决方案

声明位图:



或者分配绝对值( 1 2 4 ,...)可以声明 bitmasks (如何调用):

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

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

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

(请参阅 Abizern的答案关于后者的更多信息)



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

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

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

相当于:

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



比较位掩码:



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



检查确切的相等性:



我们假设状态是这样初始化的:

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

如果要检查状态您可以使用

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

相当于:

  00000101 //(FileNotDownloaded | FileDownloaded)
== 00000100 // FileDownloaded
-----------
= 00000000 //检查会员资格:



< >如果要检查状态包含 FileNotDownloaded ,则需要使用:

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

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

看到微妙的差异(以及为什么你当前的if表达可能是错误的) / p>

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

view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

I have a custom UIView with multiple states, which I have defined in an enum like this:

enum DownloadViewStatus {
  FileNotDownloaded,
  FileDownloading,
  FileDownloaded
};

For each created subview, I set its tag: subview1.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 subview1 shows 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.

Is there a way to do that?

解决方案

Declaring Bitmasks:

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

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

or using modern ObjC's NS_OPTIONS/NS_ENUM macros:

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

(see Abizern's answer for more info on the latter)

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

Hence ORing two values does the following:

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:

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

If you want to check if status equals FileNotDownloaded, you can use:

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 status merely contains FileNotDownloaded, you need to use:

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)?

这篇关于在Objective-C中声明和检查/比较(bitmask-)枚举的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆