杂文小品

iOS中NS_OPTIONS 位移枚举详解

2020-03-14  本文已影响0人  MiniCoder

OC中NS_OPTIONS的使用

OC 常用的枚举有两种类型,分别是 NS_ENUM 和 NS_OPTIONS ,
普通使用推荐枚举NS_ENUM 方式,
需要安位或操作组合的方式就使用枚举NS_OPTIONS ,还有个功能就是可以多选

typedef NS_ENUM(NSUInteger, YLEnum) {
    YLEnumTop           = 1,    // 0000 0001
    YLEnumBottom      ,       // 0000 0010
    YLEnumLeft           ,       // 0000 0011
    YLEnumRight        ,       // 0000 0100
};
typedef NS_OPTIONS(NSUInteger, YLOptions) {
    YLOptionsTop           =  1 << 0,   // 0000 0001
    YLOptionsBottom        =  1 << 1,   // 0000 0010
    YLOptionsLeft          =  1 << 2,   // 0000 0100
    YLOptionsRight         =  1 << 3,   // 0000 1000
};

PS: 位移枚举 YLOptions 第一个枚举值是 YLOptionsTop , 如果该枚举值 !=0,那么可以默认传0做参数,这时效率最高(因为在方法 optionsDemo: 中可以什么都不用做了)

[self optionsDemo:YLOptionsTop | YLOptionsRight];
  //多选时,用加法来进行枚举的叠加,减法来进行枚举的删除
  //根据打印可以知道 type == 9
  // type 是 top 和 right 相加得来的
  // 0000 0001 + 0000 1000 = 0000 1001  即为 9
- (void)optionsDemo:(YLOptions)type{
    //根据下面的 按位运算 就可以计算出结果了
    //1001 & 0001   0001
    if (type & YLOptionsTop) {
        NSLog(@"上  %ld",type & YLOptionsTop);
    }
    //1001 & 0010   0000
    if (type & YLOptionsBottom) {
        NSLog(@"下  %ld",type & YLOptionsBottom);
    }
    //1001 & 0100   0000
    if (type & YLOptionsLeft) {
        NSLog(@"左  %ld",type & YLOptionsLeft);
    }
    //1001 & 1000   1000
    if (type & YLOptionsRight) {
        NSLog(@"右  %ld",type & YLOptionsRight);
    }
}
1 | 1 = 1  
1 | 0 = 1  
0 | 0 = 0       
总结规则: 有1则为1   即:一真则真

解析的时候:按位 与 ‘&’ 运算 :

1 & 1 = 1  
1 & 0 = 0   
0 & 0 = 0
总结规则:有0则为0 即:一假则假

Swift Optionsets

对于位掩码,Swift 给出的方案是:选项集合(option sets)。在 C 和 Objective-C 中,通常的做法是将一个布尔值选项集合表示为一系列值为 2 的整数次幂的枚举成员。之后就可以使用位掩码来选择想要的选项了

使用结构体(struct来遵从 OptionSet 协议,以引入选项集合,而非枚举(enum。为什么这样处理呢?当枚举成员互斥的时候,比如说,一次只有一个选项可以被选择的情况下,枚举是非常好的。但是和 C 不同,在 Swift 中,你无法把多个枚举成员组合成一个值,而 C 中的枚举对编译器来说就是整型,可以接受任意整数值。

和 C 中一样,Swift 中的选项集合结构体使用了高效的位域来表示,但是这个结构体本身表现为一个集合,它的成员则为被选择的选项。这允许你使用标准的集合运算来维护位域,比如使用 contains 来检验集合中是否有某个成员,或者是用 union 来组合两个位域

struct  CollecLayoutType : OptionSet {
    let rawValue: UInt
    static let CollecLayoutType_1 =  CollecLayoutType(rawValue: 1 << 0)
    static let CollecLayoutType_2 =  CollecLayoutType(rawValue: 1 << 1)
    static let CollecLayoutType_3 =  CollecLayoutType(rawValue: 1 << 2)
    static let CollecLayoutType_HNews =  CollecLayoutType(rawValue: 1 << 3)
    static let CollecLayoutType_BaseCell =
        [CollecLayoutType_1, CollecLayoutType_2, CollecLayoutType_3]
}

使用:

let options: CollecLayoutType = [.CollecLayoutType_1, .CollecLayoutType_2]  // 3 (= 1 + 2)
let op1 = options.contains(.CollecLayoutType_1)          // → true
let op2 = options.contains(.CollecLayoutType_HNews)  // → false
let op3 =  options.union([.CollecLayoutType_3]) // → 7 (= 1 + 2 + 4)
let type: CollecLayoutType = .CollecLayoutType_1
if (type  == .CollecLayoutType_1) {  // → true
    // TODO
}
if (CollecLayoutType.CollecLayoutType_BaseCell.contains(type)) { // → true
    // TODO
}
上一篇下一篇

猜你喜欢

热点阅读