iOS开发中的常客-枚举

枚举,enum,C语言特性。

由于Objective-C基于C语言,所以也有enum。

其实在阅读API或者系统框架时候经常会看到此类型。但在实际开发中,我们往往会忽视它的作用。在一系列常量来表示错误状态、类型、可组合选项等得时候,我们均可使用枚举为其命名。

枚举,其实只是一种常量命名的方式。

它是一个整形(int) ,一般是4个字节的int值,在64位系统上是8个字节。并且,它不参与内存的占用和释放,枚举定义变量即可直接使用,不用初始化。在代码中使用枚举的目的有一个,那就是增加代码的可读性。


主要有三种方式:

1、enum

这是C语言风格,例如:

enum{

TypeA ,

TypeB,

TypeC,

};

typedef enum{

TypeA ,

TypeB,

TypeC,

}TypeName;

数据枚举的顺序规定了枚举数据的序号,从0开始,依次递增。 TypeA=0,TypeB=1,TypeC=2。我们还可以从某个值开始或者全部指定值,例如:

enum{

TypeA = 3 ,

TypeB,

TypeC,

};

那么TypeB=4,TypeC=5。

2、NS_ENUM 、NS_OPTIONS

OC中常见的枚举,例如常见的:

typedef NS_ENUM(NSInteger, UIViewAnimationCurve) {

UIViewAnimationCurveEaseInOut,         // slow at beginning and end

UIViewAnimationCurveEaseIn,            // slow at beginning

UIViewAnimationCurveEaseOut,           // slow at end

UIViewAnimationCurveLinear

};
typedef NS_OPTIONS(NSUInteger, UIViewAnimationOptions) {

UIViewAnimationOptionLayoutSubviews            = 1 <<  0,

UIViewAnimationOptionAllowUserInteraction      = 1 <<  1, // turn on user interaction while animating

UIViewAnimationOptionBeginFromCurrentState     = 1 <<  2, // start all views from current value, not initial value

UIViewAnimationOptionRepeat                    = 1 <<  3, // repeat animation indefinitely

UIViewAnimationOptionAutoreverse               = 1 <<  4, // if repeat, run animation back and forth

UIViewAnimationOptionOverrideInheritedDuration = 1 <<  5, // ignore nested duration

UIViewAnimationOptionOverrideInheritedCurve    = 1 <<  6, // ignore nested curve

UIViewAnimationOptionAllowAnimatedContent      = 1 <<  7, // animate contents (applies to transitions only)

UIViewAnimationOptionShowHideTransitionViews   = 1 <<  8, // flip to/from hidden state instead of adding/removing

UIViewAnimationOptionOverrideInheritedOptions  = 1 <<  9, // do not inherit any options or animation type

UIViewAnimationOptionCurveEaseInOut            = 0 << 16, // default

UIViewAnimationOptionCurveEaseIn               = 1 << 16,

UIViewAnimationOptionCurveEaseOut              = 2 << 16,

UIViewAnimationOptionCurveLinear               = 3 << 16,

UIViewAnimationOptionTransitionNone            = 0 << 20, // default

UIViewAnimationOptionTransitionFlipFromLeft    = 1 << 20,

UIViewAnimationOptionTransitionFlipFromRight   = 2 << 20,

UIViewAnimationOptionTransitionCurlUp          = 3 << 20,

UIViewAnimationOptionTransitionCurlDown        = 4 << 20,

UIViewAnimationOptionTransitionCrossDissolve   = 5 << 20,

UIViewAnimationOptionTransitionFlipFromTop     = 6 << 20,

UIViewAnimationOptionTransitionFlipFromBottom  = 7 << 20,

} NS_ENUM_AVAILABLE_IOS(4_0);

这两个宏的定义在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)。


什么时候需要用到NS_OPTIONS呢?

当枚举变量可能要代表多个枚举值的时候。引用网上说法就是“其实给一个枚举变量赋予多个枚举值的时候,原理只是把各个枚举值加起来。当加起来以后,就获取了一个新的值,那么为了保证这个值的唯一性,这个时候就体现了位运算的重要作用,位运算可以确保枚举值组合的唯一性,因为位运算的计算方式是将二进制转换成十进制,也就是说,枚举值里面存取的是计算后的十进制值。”

还有就是在定义选项的时候,并且这些选项可以彼此组合。只要枚举定义得对,各选项之间就可通过“按位或操作符”(bitwise OR operator)来组合。例如,iOS UI框架中有如下枚举类型,用来表示某个视图应该如何在水平或垂直方向上调整大小:

enum UIViewAutoresizing {

   UIViewAutoresizingNone                 = 0,

   UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,

   UIViewAutoresizingFlexibleWidth        = 1 << 1,

   UIViewAutoresizingFlexibleRightMargin  = 1 << 2,

   UIViewAutoresizingFlexibleTopMargin    = 1 << 3,

   UIViewAutoresizingFlexibleHeight       = 1 << 4,

   UIViewAutoresizingFlexibleBottomMargin = 1 << 5,

}

 

每个选项均可启用或禁用,使用上述方式来定义枚举值即可保证这一点,因为在每个枚举值所对应的二进制表示中,只有1个二进制位的值是1。用“按位或操作符”可组合多个选项,例如:UIViewAutoResizingFlexibleWidth| UIViewAutoresizingFlexibleHeight。下图中列出了每个枚举成员的二进制值,并演示了刚才那两个枚举组合之后的值。用“按位与操作符”(bitwise AND operator)即可判断出是否已启用某个选项:

enum UIViewAutoresizing resizing =

   UIViewAutoresizingFlexibleWidth |

   UIViewAutoresizingFlexibleHeight;

if (resizing & UIViewAutoresizingFlexibleWidth) {

      // UIViewAutoresizingFlexibleWidth is set

}

枚举使用中的注意事项:

1、应该用枚举来表示状态机的状态、传递给方法的选项以及状态码等值,给这些值起个易懂的名字。

2、如果把传递给某个方法的选项表示为枚举类型,而多个选项又可同时使用,那么就将各选项值定义为2的幂,以便通过按位或操作将其组合起来。

3、用NS_ENUM与NS_OPTIONS宏来定义枚举类型,并指明其底层数据类型。这样做可以确保枚举是用开发者所选的底层数据类型实现出来的,而不会采用编译器所选的类型。

4、在处理枚举类型的switch语句中不要实现default分支。这样的话,加入新枚举之后,编译器就会提示开发者:switch语句并未处理所有枚举。

 

尊重原创内容,转载请注明出处
本文链接地址: https://www.awnlab.com/archives/110

为您推荐

发表评论

邮箱地址不会被公开。 必填项已用*标注