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?
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)
One thing to keep in mind when checking against bitmasks:
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
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)?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With