什么是Swift枚举字节表示?

时间:2016-07-11 11:37:27

标签: swift enums nsdata

我有以下枚举:

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的通用函数。

2 个答案:

答案 0 :(得分:3)

Swift ABI仍在进行中(预计将使用Swift 4修复)。枚举的方式在内存is described here中表示。

您的案例是"c-like enum",因为有......

  • 两个或两个以上的案例
  • 没有关联的值

引用ABI文件:

  

枚举被布置为整数标记,其中包含所有大小写的最小位数。 [...]案例按声明顺序分配标签值。

这里的关键信息是"最小位数"。这意味着(对于您的情况)实例应该适合两位(因为您有三种情况)。 rawValue 0x10需要五位 - 这将与ABI冲突。

编译器可能使用静态表在EnumrawValue(以及后面)的实例之间进行转换。

这是一个突出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 = 0B = 1B2 = 2C = 3