Sil*_*ntK 5 enums enumeration objective-c
为什么有这么多不同的方法在目标c中声明枚举?这很令人困惑.
以下是否有任何区别或它们是否完全相同?
enum WeekDays{
Monday,
Tuesday,
Wednesday,
Thursday,
Friday
};
typedef enum : NSUInteger {
Monday,
Tuesday,
Wednesday,
Thursday,
Friday
} WeekDays;
typedef NS_ENUM(NSInteger, WeekDays){
Monday,
Tuesday,
Wednesday,
Thursday,
Friday
};
enum {
Monday,
Tuesday,
Wednesday,
Thursday,
Friday
};
typedef NSInteger WeekDays;
Run Code Online (Sandbox Code Playgroud)
CRD*_*CRD 14
以下是否有任何区别或它们是否完全相同?
存在差异,一些是由于C - 它们是Objective-C的基础 - 而另一个则是考虑将Objective-C代码导入Swift.
你的第一个例子:
enum WeekDays { Monday, ..., Friday };
Run Code Online (Sandbox Code Playgroud)
是原来的C enum.这声明了一个类型 enum WeekDays,其基础类型为int5个字面值.
现在C不是强类型语言:这里的文字值没有类型enum WeekDays,而是类型int; 并且enum WeekDays可以为类型的变量分配除Monday直通之外的值Friday,并将其分配给int没有强制转换或转换的变量.第一个文字值(Monday此处)将具有该int值0,并且后面的值将比前一个文字大一个值(因此这里Friday有值4).例子:
enum WeekDays one;
int two;
one = Monday;
two = Tuesday; // assigning enum literal to int is OK
two *= 42; // will produce an int value outside of Monday thru Friday
one = two; // which can be assigned to an enum WeekDays
one = 34; // int values can also be directly assigned
Run Code Online (Sandbox Code Playgroud)
所有的enum变化都在这样弱.然而,在某些情况下,许多编译器(包括至少从v8开始使用的那些编译器)将发出警告(而不是错误),例如,如果switch表达式是一种enum类型,并且case标签要么省略一些声明的文字,要么具有超出声明值的值.
给文字明确的价值观
不是依赖于默认值,而是可以为enum文字赋予特定值.例如,得到Monday的值1通过以Friday具有值5:
enum WeekDays { Monday = 1, ..., Friday };
Run Code Online (Sandbox Code Playgroud)
没有显式值的文字像往常一样被分配比前面的文字多一个.这些值也不需要是连续的:
enum WeekDays { Monday = 1, Tuesday = 42, Wednesday = 3, Thursday, Friday };
Run Code Online (Sandbox Code Playgroud)
用一个 typedef
许多C类型声明很复杂且难以解析(它们是离题测验问题),C typedef允许声明特定类型的别名.A typedef通常与enum声明一起使用,以避免enum在使用类型时使用.例如:
typedef enum WeekDays { Monday, ..., Friday } WeekDays;
Run Code Online (Sandbox Code Playgroud)
声明别名WeekDays是指enum WeekDays.例如:
WeekDays one; // means exactly the same as the previous
// declaration for one
enum WeekDays one; // also valid and means the same thing
Run Code Online (Sandbox Code Playgroud)
WeekDays在上述声明中看到两次可能会让人感到困惑,或者只是为某些人打字太多,而且可以省略:
typedef enum { Monday, ..., Friday } WeekDays;
Run Code Online (Sandbox Code Playgroud)
这与之前的声明略有不同,WeekDays现在是匿名 的别名enum.使用这种类型,第一种声明形式现在无效:
enum Weekdays one; // invalid, no such enum
WeekDays one; // valid
Run Code Online (Sandbox Code Playgroud)
更改基础类型
默认情况下,a的基础类型enum是int.可以指定不同的整数类型,类型必须足够大以容纳文字所代表的所有值.整数类型是整数,无符号整数和字符类型.通过: <type>在enum标记之后添加来指定基础类型,并且可以为文字指定相同类型的特定值.例如:
typedef enum Vowels : char { Letter_A = 'a', ..., Letter_U = 'u' } Vowels;
Run Code Online (Sandbox Code Playgroud)
如上所述,可以使用匿名枚举:
typedef enum : char { Letter_A = 'a', ..., Letter_U = 'u' } Vowels;
Run Code Online (Sandbox Code Playgroud)
运用 NS_ENUM
NS_ENUM是一个(Apple)Objective-C便利宏,它扩展为a typedef和enum声明.例如:
typedef NS_ENUM(NSInteger, WeekDays) { Monday, ..., Friday };
Run Code Online (Sandbox Code Playgroud)
扩展为:
typedef enum WeekDays : NSInteger WeekDays;
enum WeekDays : NSInteger { Monday, ..., Friday };
Run Code Online (Sandbox Code Playgroud)
避免前向声明相当于:
typedef enum WeekDays : NSInteger { Monday, ..., Friday } WeekDays;
Run Code Online (Sandbox Code Playgroud)
至少使用Xcode v8,使用NS_ENUM和直接使用之间的编译器检查和警告没有区别typedef.
当NS_ENUM有所作为
如果您正在编写将由Swift使用的Objective-C,那么使用NS_ENUM确实会产生影响:声明使用的枚举NS_ENUM将作为Swift导入enum; 而直接声明的一个将被导入为Swift struct和一个全局只读计算属性的集合,每个文字一个.
为什么存在这种差异在当前的Apple文档中没有解释(使用Swift with Cocoa和Objective-C(Swift 4.0.3),可通过iBooks获得)
最后,回到你的例子
以上应该可以让你找出差异:
默认C enum,底层类型是int,类型用作enum WeekDays
别名C enum,底层类型是NSUinteger,类型用作WeekDays
NS_ENUM生成enum,底层类型是NSInteger,类型可以称为WeekDays或enum WeekDays
这声明了两种不同的类型,可能会产生警告.第一个是enum没有别名的匿名,因此以后不会引入此类型的变量.它引入的文字是类型int.第二个是别名NSInteger.在64位系统上NSInteger是64位,int而是32位,因此在文字类型(int)和"枚举"类型(WeekDays)之间的分配可能会产生警告.进一步的switch陈述不会像之前的三个版本那样进行检查,因为它们只是基于NSInteger.这个版本看起来像是一个不正确的模拟尝试,NS_ENUM不应该使用(它本身是无效的,只是没有做它的建议).
希望所有这些都能让人感到困惑!