我有以下枚举:
enum Enum: UInt8
{
case A = 0x00
case B = 0x01
case C = 0x10
}
我使用以下代码将其转换为NSData
:
var value = Enum.C
let data = NSData(bytes: &value, length: 1)
当然,我希望data
包含 0x10
,但它包含 0x02
。
对于Enum.A
,它包含0x00
,对于Enum.B
,它包含0x01
。
对我来说,它看起来像存储了一个值的索引而不是它的实际原始数据。有人可以解释这种行为吗?
P.S。如果我使用rawValue
它完美无缺。但是,我想了解背后的原因,因为我因此无法创建将值转换为NSData的通用函数。
答案 0 :(得分:3)
Swift ABI仍在进行中(预计将使用Swift 4修复)。枚举的方式在内存is described here中表示。
您的案例是"c-like enum",因为有......
引用ABI文件:
枚举被布置为整数标记,其中包含所有大小写的最小位数。 [...]案例按声明顺序分配标签值。
这里的关键信息是"最小位数"。这意味着(对于您的情况)实例应该适合两位(因为您有三种情况)。 rawValue 0x10
需要五位 - 这将与ABI冲突。
编译器可能使用静态表在Enum
和rawValue
(以及后面)的实例之间进行转换。
这是一个突出ABI特征的例子:
enum Enum: UInt32
{
case A = 0
case B = 0xffffffff // value that does not fit into one byte
}
assert(sizeof(Enum.self) == 1)
答案 1 :(得分:1)
每个枚举案例都有一个标准的订单值。当您不使用.rawValue
时,您将获得以下内容。
例如,如果您将枚举更改为:
enum Enum: UInt8
{
case A = 0x00
case B = 0x01
case B2 = 0x0A
case C = 0x10
}
然后,执行时
var value = Enum.C
let data = NSData(bytes: &value, length: 1)
data
将为3
,因为A = 0
,B = 1
,B2 = 2
,C = 3