tmyam's blog

time run off...

Objective-C枚举介绍

Objective-C枚举的使用,常见的方式总结,以便自己使用时方便查阅。

1. 枚举介绍

enum only

1
2
3
4
5
enum
{
    TMEnumTestOne,
    TMEnumTestTwo,
};
  • 这种枚举不推荐使用,因为不能用一种类型的方式表示枚举。

enum 类型

1
2
3
4
5
6
typedef enum
{
    TMEnumTestOne,
    TMEnumTestTwo,

} TMEnumTest;
1
2
3
4
5
6
enum TMEnumTest
{
    TMEnumTestOne,
    TMEnumTestTwo,
};
typedef enum TMEnumTest TMEnumTest;
  • 这两种写法,将枚举描述为一个类型TMEnumTest
    但是这种写法也有局限性,在作为函数参数时,如果传入NSInteger类型的数据,则需要强制转换,否则会有类型不匹配的警告,所以这种方式也不推荐。如下图, temp

老式enum写法

1
2
3
4
5
6
enum
{
    TMEnumTestOne,
    TMEnumTestTwo,
};
typedef NSUInteger TMEnumTest;
  • 这种写法可以指定TMEnumTest的类型,并且作为函数参数时,传入的值不需要进行强制类型转换。
    但是这种写法不会检查枚举的正确性,是好是坏需要自己判断,如下图。本人推荐这种写法。 temp

新式enum写法

1
2
3
4
5
typedef NS_ENUM(NSUInteger, TMEnumTest)
{
    TMEnumTestOne,
    TMEnumTestTwo,
};
1
2
3
4
5
typedef NS_OPTIONS(NSUInteger, TMEnumTest)
{
    TMEnumTestOne  = 0,
    TMEnumTestTwo  = 1 << 0,
};
  • NS_ENUMNS_OPTIONS本质是一样的,仅仅从字面上来区分用途。NS_ENUM是通用情况,NS_OPTIONS一般用来定义位枚举。 参考链接
  • 这种写法同样作为函数参数时,传入的值不需要进行强制类型转换。但是也同样不会检查枚举的正确性,和 老式enum写法 一样,如下图。 temp
  • 但是不同的是,新式enum写法 在使用switch时,会进行值的检测,如果枚举中无此值,则会弹出警告,如下图。这种方式见仁见智了。本人推荐这种写法。 temp

2. 枚举最大值

对于一般的枚举,要获取枚举的最大值是很难的,因为随着枚举的扩充,最大值在不断变化,这时推荐使用一个固定的枚举表示最大值,例如:

1
2
3
4
5
6
7
typedef NS_ENUM(NSUInteger, TMEnumTest)
{
    TMEnumTestOne,
    TMEnumTestTwo,

    TMEnumTestMax,  // 表示最大值
};

这样就可以使用TMEnumTestMax表示枚举TMEnumTest的最大值了。

3. 位枚举

位枚举是一种特殊的枚举,在apple的类中使用的很多,例如NSStringCompareOptions等。

1
2
3
4
5
6
7
typedef NS_OPTIONS(NSUInteger, TMEnumTest)
{
    TMEnumTestOne     = 0,          // 0
    TMEnumTestTwo     = 1 << 0,     // 1
    TMEnumTestThree   = 1 << 1,     // 2
    TMEnumTestFour    = 1 << 2,     // 4
};

  • 位枚举的特点是可以使用位运算来处理枚举值,实际使用中可以用一个变量存储多个枚举值,表示互不影响的多个设置。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
- (void) test
{
    TMEnumTest test = TMEnumTestTwo|TMEnumTestThree;  // 3

    /* 添加TMEnumTestFour到test中(如test已经包含TMEnumTestFour,则test值不变)
    
       当然这里也可以使用test += TMEnumTestFour,
       但是注意 + 不能在test中已经包含TMEnumTestFour的情况下使用。
    */
    test |= TMEnumTestFour;  // 7


    /* 将TMEnumTestThree从test中去除(如test不包含TMEnumTestThree,则test值不变)
    
       当然这里也可以使用test -= TMEnumTestThree,
       但是注意 - 不能在test中不包含TMEnumTestThree的情况下使用。
    */
    test &= ~TMEnumTestThree; // 5


    // 判断 TMEnumTestFour枚举 是否被包含
    if ((test & TMEnumTestFour) == TMEnumTestFour)
    {
        NSLog(@"YES");
    }


    /* 判断 TMEnumTestFour枚举 是否被包含
     
     因为 (test & TMEnumTestFour) 的结果不是 0,就是TMEnumTestFour本身,
     而 TMEnumTestFour > 0 ,所以可以使用简易的判断
     */
    if (test & TMEnumTestFour)
    {
        NSLog(@"YES");
    }
}

评论