2016-07-11 5 views
3

я следующее перечисление:Что такое представление байтового перечисления Swift?

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

В этом случае размер значения в байтах точно ** 1 ** (я использовал 'sizeof' вместо' 1') , Таким образом, это означает, что единственное, что сохранилось, - это номер заказа. – Werolik

ответ

3

Swift ABI все еще работает (ожидается, что будет зафиксирован wi th 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) 
+0

Это объясняет это, спасибо. Похоже, мне нужно будет использовать определенную перегрузку RawValueRepresentable' для преобразования перечислений в NSData. – Werolik

+0

@Werolik Похоже, хорошая идея не полагаться на особенности ABI для создания такого рода общих функций преобразования на данный момент. –

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

+1

Можете ли вы обратиться к какой-то части документации для этого? – Werolik

Смежные вопросы