以下有什么区别还是都一样?
存在一些差异,其中一些是由于 C - 它是 Objective-C 的基础 - 如果您正在考虑将 Objective-C 代码导入 Swift。
你的第一个例子:
enum WeekDays { Monday, ..., Friday };
是一个原始的 C enum。这声明了一个类型enum WeekDays,其基础类型为int,以及5个文字值。
现在 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
所有enum 变体在这种情况下很弱。然而,许多编译器,包括至少从 v8 开始由 Xcode 使用的编译器,在某些情况下会发出警告(而不是错误),例如如果switch 表达式是enum 类型并且case 标签省略了一些声明的文字或具有声明值之外的值。
给文字明确的值
可以将特定值赋予enum 文字,而不是依赖默认值。例如,将 Monday 的值 1 赋予到 Friday 的值 5:
enum WeekDays { Monday = 1, ..., Friday };
没有显式值的文字像往常一样被分配比前面的文字多一个。这些值也不需要是连续的:
enum WeekDays { Monday = 1, Tuesday = 42, Wednesday = 3, Thursday, Friday };
使用typedef
许多 C 类型声明很复杂且难以解析(它们是质询题),C typedef 允许声明特定类型的别名。 typedef 通常与 enum 声明一起使用,以避免在使用类型时必须使用 enum。例如:
typedef enum WeekDays { Monday, ..., Friday } WeekDays;
声明别名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
在上面的声明中看到WeekDays 两次可能会造成混淆,或者对某些人来说输入太多,可以省略:
typedef enum { Monday, ..., Friday } WeekDays;
这与之前的声明略有不同,WeekDays 现在是 匿名 enum 的别名。对于这样的类型,第一种形式的声明现在是无效的:
enum Weekdays one; // invalid, no such enum
WeekDays one; // valid
更改底层类型
默认情况下,enum 的基础类型是 int。可以指定不同的 integral 类型,该类型必须足够大以容纳文字表示的所有值。整数类型是整数、无符号整数和字符类型。底层类型是通过在enum 标记后添加: <type> 来指定的,并且可以为文字赋予相同类型的特定值。例如:
typedef enum Vowels : char { Letter_A = 'a', ..., Letter_U = 'u' } Vowels;
如上所述,可以使用匿名枚举:
typedef enum : char { Letter_A = 'a', ..., Letter_U = 'u' } Vowels;
使用NS_ENUM
NS_ENUM 是一个 (Apple) Objective-C 便利宏,它扩展为 typedef 和 enum 声明。例如:
typedef NS_ENUM(NSInteger, WeekDays) { Monday, ..., Friday };
扩展到:
typedef enum WeekDays : NSInteger WeekDays;
enum WeekDays : NSInteger { Monday, ..., Friday };
避免前向声明相当于:
typedef enum WeekDays : NSInteger { Monday, ..., Friday } WeekDays;
至少使用Xcode v8,使用NS_ENUM和上面直接使用typedef在编译器检查和警告方面没有区别。
当NS_ENUM 有所作为时
如果您正在编写 Swift 将使用的 Objective-C,那么使用 NS_ENUM 确实会有所不同:使用 NS_ENUM 声明的枚举将作为 Swift enum 导入;而直接声明的将被导入为 Swift struct 和一组全局只读计算属性,每个文字一个。
当前的 Apple 文档中没有解释为什么存在这种差异(Using Swift with Cocoa and Objective-C (Swift 4.0.3),可通过 iBooks 获得)
最后,回到你的例子
以上内容应该可以让您找出差异:
默认Cenum,底层类型为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 的错误尝试,不应该使用(它本身是无效的,只是没有按照它的建议做)。
希望所有的东西都能照亮而不是混淆!