枚举值定义选项通过按位或来实现多选
-
使用背景
苹果官方使用的情况
- 通知中心中的option选项
<pre>NSKeyValueObservingOptionNew = 0x01,
NSKeyValueObservingOptionOld = 0x02,
NSKeyValueObservingOptionInitial NS_ENUM_AVAILABLE(10_5, 2_0) = 0x04,
NSKeyValueObservingOptionPrior NS_ENUM_AVAILABLE(10_5, 2_0) = 0x08</pre> - UIView中调整大小的一个枚举值
<pre>typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};</pre>
调用时
<pre>[[NSNotificationCenter defaultCenter] addObserver:self forKeyPath:self.textField.text options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
</pre>
说明
<pre> options:NSKeyValueObservingOptionNew| NSKeyValueObservingOptionOld </pre>表示New选项和Old选项都被选中,即新值和旧值的选项都会触发.
-
自定义使用方法
<pre> typedef NS_OPTIONS(int, GCSelection){
GCSelectionA = 1 << 0,
GCSelectionB = 1 << 1,
GCSelectionC = 1 << 2,
};
@interface ViewController ()
@property (nonatomic,assign) GCSelection selection;
@end
@implementation ViewController
-(void)viewDidLoad {
[super viewDidLoad];
[self printMyEnum:GCSelectionA | GCSelectionB];
}
- (void)printMyEnum:(GCSelection)selection {
if (selection & GCSelectionA) {
NSLog(@"A");
}
if (selection & GCSelectionB) {
NSLog(@"B");
}
if (selection & GCSelectionC) {
NSLog(@"C");
}
} </pre>
输出结果
输出结果.png-
使用分析
其实原理很简单,就是将枚举值转换成2进制数.下列每个枚举值的二进制数都有且仅有一位为1,如果我们使用按位或操作符去进行选择,那么就会达到多选的效果.
- 分析原理
<pre>十六进制 --> 二进制
0x01 --> 0001
0x02 --> 0010
0x04 --> 0100
0x08 --> 1000
使用左移符号 <<
1的二进制形式是 --> 0001
1<<0 左移0位 --> 0001
1<<1 左移1位 --> 0010
1<<2 左移2位 --> 0100
1<<3 左移3位 --> 1000
</pre>
在我们使用按位或操作符选择了多个选项的时候,系统会先进行按位或,得出结果:
<pre>比如demo中的:[self printMyEnum:GCSelectionA | GCSelectionB];
按位或的计算过程是:
0001
0010
---->
0011
</pre>
现在我们选择的枚举值经过按位或操作后,有两位是1,即0011.这也就意味着我们进行了多选.所以在筛选枚举值的时候,我们用按位与就能准确得到选了哪些枚举值.
selection & GCSelectionA的计算过程是:
<pre>按位与
0011
0001
---->
0001</pre>
结果非0即真所以会打印A;
同理selection & GCSelectionB的计算过程是:
<pre>按位与
0011
0010
---->
0010</pre>
所以B也会打印.