谈谈位枚举NS_OPTIONS

在iOS开发中枚举大家用得最多的应该是NS_ENUM。NS_ENUM也没什么好讲的。主要来讲讲位枚举NS_OPTIONS。

下面是他们在Foundation.framework的NSObjCRuntime.h的定义

#if (__cplusplus && __cplusplus >= 201103L && (__has_extension(cxx_strong_enums) || __has_feature(objc_fixed_enum))) || (!__cplusplus && __has_feature(objc_fixed_enum))

#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type

#if (__cplusplus)

#define NS_OPTIONS(_type, _name) _type _name; enum : _type

#else

#define NS_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type

#endif

#else

#define NS_ENUM(_type, _name) _type _name; enum

#define NS_OPTIONS(_type, _name) _type _name; enum

#endif

其实从枚举定义来看,NS_ENUM和NS_OPTIONS本质是一样的,仅仅从字面上来区分其用途。NS_ENUM是通用情况,NS_OPTIONS一般用来定义具有位移操作或特点的情况(bitmask掩码)。

与、或操作

先讲讲关于二进制的位于操作。可能好多的同学都有些忘了。这里复习下。

位操作 解释 例子 应用
按位与(&) 有0则0,当俩位同时为1时返回1. 4=0000 0000 0000 0100 &7 =0000 0000 0000 0111= 0000 0000 0000 0100 1.清零
2.获取一个数据的指定位
3.保留数据区的特定位
按位或(I) 有1则1,只要有一位为1则即可返回1. 5 = 0000 0000 0000 0101I 7= 0000 0000 0000 0111=0000 0000 0000 0111 设定一个数据的指定位

<<:左移运算符。左移k位 相当于 *2^k
>>:右移运算符。右移k位 相当于/2^k

实例

NS_OPTIONS位枚举的特点是可以使用位运算来处理枚举值,实际使用中可以用一个变量存储多个枚举值,表示互不影响的多个设置。比如系统中的UIViewAutoresizing定义如下。

enum UIViewAutoresizing {
    UIViewAutoresizingNone                 = 0, // 000000
    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0, // 000001
    UIViewAutoresizingFlexibleWidth        = 1 << 1,// 000010
    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,// 000100
    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,// 001000
    UIViewAutoresizingFlexibleHeight       = 1 << 4,// 010000
    UIViewAutoresizingFlexibleBottomMargin = 1 << 5,// 100000
}

为了说明问题这里就用UIViewAutoresizing举个例子。上面把对应的二进制写在了后面。现在要实现视图的宽和高自适应,UIViewAutoResizingFlexibleWidth| UIViewAutoresizingFlexibleHeight。

一般会这样写:

UIViewAutoresizing resizing = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

转换为二进制计算一下。

UIViewAutoresizing resizing = 000010 |010000 = 010010

这样就实现了变量保存多个枚举值。那么如何判断变量是否包含某个枚举值了,这的通过与操作。比如我要判断是否包含了UIViewAutoresizingFlexibleWidth

if (resizing & UIViewAutoresizingFlexibleWidth) {
       // UIViewAutoresizingFlexibleWidth is set
}

转换为二进制:

if (010010 & 000010) {
       // UIViewAutoresizingFlexibleWidth is set
}

010010 & 000010 = 000010 很明显不等于0。所以为YES。那么用一个不包含的试一下。

if (resizing & UIViewAutoresizingFlexibleTopMargin) {
       // UIViewAutoresizingFlexibleTopMargin is set
}

转为二进制

if (010010 & 001000) {
       // UIViewAutoresizingFlexibleTopMargin is set
}

很明显010010 & 001000 = 0,所以能够知道resizing不包含UIViewAutoresizingFlexibleTopMargin。

通过以上的这种方式实现了一个变量保存多个枚举值。也就是NS_OPTIONS的原理。

需要注意的地方

  1. 枚举命名方式尽量用系统的风格,比如枚举名为UIViewAutoresizing,具体的值为UIViewAutoresizingNone。简单来讲就是(枚举名+状态)
  2. 如果要实现一个变量保存多个枚举值就用NS_OPTIONS。个人觉得用NS_OPTIONS完全可以替代NS_ENUM。只需要在使用的时候不用与、或操作就可以了
  3. 用NS_ENUM与NS_OPTIONS宏来定义枚举类型,并指明其底层数据类型。这样做可以确保枚举是用开发者所选的底层数据类型实现出来的,而不会采用编译器所选的类型。
  4. 在处理枚举类型的switch语句中不要实现default分支。这样的话,加入新枚举之后,编译器就会提示开发者:switch语句并未处理所有枚举。
  5. 预留一个枚举值,用于扩展或者用于表示没有的情况
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容

  • 参考资料 《编写高质量iOS与OS X代码的52个有效方法》中第5条:用枚举表示状态、选项、状态码 枚举类型的基本...
    水止云起阅读 2,403评论 0 3
  • 前言 Enumeration,enum,在程序设计语言中,一般用一个数值来代表某一状态,这种处理方法不直观,易读性...
    eryuxinling阅读 3,078评论 0 9
  • 枚举值: 它是一个整形(int) ,并且它不参加内存的占用和释放 枚举定义变量即可直接使用,不用初始化 三种类型的...
    Moker_C阅读 465评论 0 1
  • 我们最不能左右的就是别人的想法,也许你觉得自己已经做得够好了,有人会羡慕你,但还是会有人讨厌你。 有十个人就会有十...
    野厨阅读 392评论 0 0
  • 从学习时间管理到现在一个多月的时间了,叶老师在第三课也有说过写日记,记录反思自己的每一天。在第二个星期柳教...
    娇孋娇婍阅读 143评论 0 0