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