位运算之NS_OPTIONS

作者: mysteryemm | 来源:发表于2017-02-26 23:57 被阅读349次

    分享一条枚举值的小知识吧——使用NS_OPTIONS的正确姿势。
      我们常用NS_ENUMNS_OPTIONS来定义枚举,二者有何区别?使用时该如何抉择呢?这里先简单介绍一下。
      NS_ENUM多用于一般枚举,而NS_OPTIONS则多用于带有移位运算的枚举,带有移位运算的枚举多用于同一个枚举变量可以同时赋值多个枚举成员的情况,其原理就是将各个枚举值按位或(|),因为移位运算的枚举成员可以保证按位或(|)计算之后结果的唯一性,所以每种结果都能反向计算出是由哪几个枚举成员按位或(|)而成。
      我们知道,程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算说穿了,就是直接对整数在内存中的二进制位进行操作。那么使用NS_OPTIONS时应注意什么呢?
      先定义一个枚举,如下:

    typedef NS_OPTIONS(NSInteger, TestType) {
        TestTypeOne   = 1 << 1,  // 0001 --> 0010 = 2
        TestTypeTwo   = 1 << 2,  // 0001 --> 0100 = 4
        TestTypeThree = 1 << 3,  // 0001 --> 1000 = 8
    };
    

    其中枚举成员样式为:TestTypeSample = Sample << N,结果就是将Sample的二进制数向左移动N位,即Sample乘以2的N次方。
      注意:Sample必须是2的n次幂(这里的n为非负整数),因为只有这样才能保证Sample的二进制数中只存在一个1,从而才能反向计算出当前结果是有哪几个枚举成员按位或而成。如果Sample不是2的n次幂,比如取值为3,则其对应的二进制数是0011,当枚举成员通过按位或之后所得结果的二进制数为xx11,后两位必然是11,这样就会导致即使没有对0010这个成员进行按位或,通过按位与进行反向计算也会包含0010这个成员,这样就会造成错误判断。所以,使用时要注意Sample的取值为2的n次幂。代码样例如下:

    TestType type = TestTypeOne | TestTypeTwo; //00000010 + 00000100 = 00000110 -> 6
        if (type & TestTypeOne) {  //00000110 & 00000010 = 00000010 -> 2
            NSLog(@"包含 one");
        }
        if (type & TestTypeTwo) {  //00000110 & 00000100 = 00000100 -> 4
            NSLog(@"包含 two");
        }
        if (type & TestTypeThree) { //00000110 & 00001000 = 00000000 -> 0
            NSLog(@"包含 three");
        }
    

    打印结果:


    相关文章

      网友评论

      本文标题:位运算之NS_OPTIONS

      本文链接:https://www.haomeiwen.com/subject/anmawttx.html