背景
对于开发者来说,枚举是最普通不过的一种开发手段。它通常用来定义一种类型的状态,这个状态可能有2个,也可能有7,8个或者更多。举个例子:
typedef NS_ENUM(NSInteger, ShareType) {
ShareType_Unknown = 0,
ShareType_WeiXinGroup = 1 ,
ShareType_WeiXinFriend = 2,
ShareType_SMS = 3,
ShareType_WeiboShare = 4,
ShareType_WeiboAuthor = 5,
ShareType_QQAuthor = 6,
ShareType_QQShareQZone = 7,
ShareType_link = 8,
};
这是一个定义分享类型的枚举,一共9中分享类型。
不优雅的地方
接下来我们来看一下这样定义有什么不妥的地方。
- 场景一
如果想辨识是哪一种分享类型,我们可能会这么写
if (type == ShareType_WeiXinGroup) {
doShare1();
}
好像没啥问题。
- 场景二
那如果我们想让这个type是ShareType_WeiXinGroup,ShareType_WeiXinFriend,ShareType_QQAuthor,ShareType_QQShareQZone中的一个时,做doShare1();
那么我们就会这样写代码:
if (type == ShareType_WeiXinGroup ||
type == ShareType_WeiXinFriend ||
type == ShareType_QQAuthor ||
type == ShareType_QQShareQZone) {
doShare1();
}
如果你有代码洁癖的话可能就看不惯这样的代码了。
那么有没有稍微优雅的写法呢?
答案是肯定的。
优雅的写法
我们重新定义这个枚举值
typedef NS_OPTIONS(NSInteger, ShareType) {
ShareType_Unknown = 1 << 0,
ShareType_WeiXinGroup = 1 << 1,
ShareType_WeiXinFriend = 1 << 2,
ShareType_SMS = 1 << 3,
ShareType_WeiboShare = 1 << 4,
ShareType_WeiboAuthor = 1 << 5,
ShareType_QQAuthor = 1 << 6,
ShareType_QQShareQZone = 1 << 7,
ShareType_link = 1 << 8,
};
回头看上面的两个场景:
- 场景一
我们的代码如下:
if (type & ShareType_WeiXinGroup) {
doShare1();
}
- 场景二
NSInteger fitableTypes = ShareType_WeiXinGroup | ShareType_WeiXinFriend | ShareType_QQAuthor | ShareType_QQShareQZone;
if (type & fitableTypes) {
doShare1();
}
我们看到场景一的情况好像优势不是很大,但是场景二就充分体现了它的优雅性。
原理
其实就是简单的用了二进制中的位移运算(<<),&运算符以及 | 运算符
例如
##场景一
ShareType_Unknown = 1 << 0, 二进制的表示为 01
ShareType_WeiXinGroup = 1 << 1, 二进制的表示为 10
ShareType_Unknown & ShareType_WeiXinGroup
01
10
二进制每一位进行&运算 结果为 00 判断不通过
ShareType_WeiXinGroup & ShareType_WeiXinGroup
10
10
二进制每一位进行&运算 结果为 10 判断通过
##场景二
ShareType_WeiXinGroup | ShareType_WeiXinFriend | ShareType_QQAuthor | ShareType_QQShareQZone
0000010
0000100
0100000
1000000
二进制每一位进行|运算 结果为1100110 记为A
ShareType_WeiXinGroup & A 二进制每一位进行&运算 结果为0000010 判断通过
ShareType_link & A 二进制每一位进行&运算00000000 判断不通过
适用场景
当枚举的类型相对较多的时候,推荐使用该种写法,让代码更加优雅。
当枚举的类型相对较少(2个或者3个)的时候,两种写法没什么差别。