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

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


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


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

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

Further Reference:


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

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