在Objective-C中声明和检查/比较(bitmask-)枚举 [英] Declaring and checking/comparing (bitmask-)enums in Objective-C
问题描述
<$ 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 OR
ing 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屋!