2016-07-11 4 views
3

私は、次の列挙型があります:私はNSDataに変換するには、次のコードを使用しスウィート列挙型バイト表現とは何ですか?

enum Enum: UInt8 
{ 
    case A = 0x00 
    case B = 0x01 
    case C = 0x10 
} 

を:

var value = Enum.C 
let data = NSData(bytes: &value, length: 1) 

当然のことながら、私はdata0x10が含まれていることを期待するが、しかし、それは、0x02が含まれています

Enum.Aについては、0x00を含み、Enum.Bの場合、0x01を含む。

私にとっては、実際の生データの代わりに値のインデックスが格納されているようです。誰かがこの行動を説明できますか?

P.S.私がrawValueを使用すれば、それは完全に動作します。しかし、なぜなら、NSDataに値を変換する汎用関数を作成することができないため、理由を理解したいのです。

+0

この場合、バイト単位の値の大きさが正確** 1 **(私は 'sizeof'代わりに '1'を使用)であります。つまり、保存されるのは注文番号のみです。 – Werolik

答えて

3

スイフトABIはまだ進行中です(スウィフト4)。列挙型の方法はメモリis described hereに表されています。

列挙型:ISは持っているので

あなたの場合は

  • 2以上の場合
  • なし関連する値

ABIの文書を引用し... "c-like enum"ですすべての場合を含む最小限のビット数を持つ整数タグとして配置されます。 [...]ケースには宣言順のタグ値が割り当てられます。

ここで重要な情報は「最小ビット数」です。つまり、(あなたのケースでは)インスタンスは2ビットに収まる必要があります(3つのケースがあります)。 rawValue 0x10には5ビットが必要です。これは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

これは、ありがとう、説明します。 NSDataに列挙型を変換するために、特定の 'RawValueRepresentable'オーバーロードを使用する必要があるようです。 – 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 = 0B = 1B2 = 2C = 3

+1

これについてはドキュメントの一部を参照できますか? – Werolik

関連する問題