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

You know that Cocoa has this thing, for example, you can create a UIView and do:

 view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 

I have a custom UIView with several states that I defined in enum as follows:

 enum DownloadViewStatus { FileNotDownloaded, FileDownloading, FileDownloaded }; 

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

Then I have a custom parameter 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'm trying to do is resolve this:

 subview1.tag = FileNotDownloaded | FileDownloaded; 

So, my subview1 appears in two states of my view. Currently, it is not displayed in either of these two states, because the operator | seems to add two enumeration values.

Is there any way to do this?

+71
c enums objective-c cocoa bitmask
Apr 23 '13 at 10:22
source share
3 answers

Bitmask declaration:

Alternatively, to assign absolute values ​​( 1 , 2 , 4 , ...) you can declare bitmasks (as they are called) as follows:

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

or using modern ObjC macros NS_OPTIONS / NS_ENUM :

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

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

The concept of a bitmask is to (usually) define each enumeration value with a single set of bits.

Therefore, OR entering two values ​​does the following:

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

which is equivalent to:

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

Bitmask comparison:

One thing to keep in mind when checking bitmax:

Exact equality check:

Assume that the status is initialized as follows:

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

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

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

which is equivalent to:

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

Membership Check:

If you want to check that status just 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 is your current β€œif” expression probably wrong)?

+257
Apr 23 '13 at 11:07 on
source share

While @Regexident provided an excellent answer - I should mention the modern Objective-C way of declaring enumerated options using NS_OPTIONS :

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

Additional link:

+18
Apr 23 '13 at 11:33
source share
 enum DownloadViewStatus { FileNotDownloaded = 1, FileDownloading = 2, FileDowloaded = 4 }; 

This allows you to efficiently perform bitwise operations OR and AND.

+1
Apr 23 '13 at
source share



All Articles