2015-11-19 5 views
5

let rawDataFromArray = NSData(bytes: myArray, length: ???)を使用したいのですが、配列のバイト長を取得する方法がわかりません。ここに私の配列は何ができるかのいくつかの例は以下のとおりです。Swiftの任意の配列のバイトサイズを取得する方法は?

let arr1 = [1, 2, 3] 
let arr2 = [1.0, 23556789000.0] 
let arr3 = ["hello", "ok", ""] 

func arrayLength(myArray: Array) -> Int { 
    var bytes = 0 
    for object in myArray { 
     // not sure what to do here 
    } 
    return bytes 
} 

絵文字がそれらを代表する多くのバイトを持っている可能性があるので、私は、配列の各要素(通って、すべての文字を通過する文字列の場合に行くかどうかわからないんだけど)それを行う適切な方法です。

配列のバイトサイズを取得する方法は?
誰も私にそれを行う適切な方法を教えてもらえますか?
SwiftのArrayNSDataに変換するのは良い方法ではないのでしょうか?

私はまた、Converting Swift Array to NSData for persistent storageConverting array of bytes to NSDataCustom Array to NSDataを見ましたが、そのような任意の配列のバイトサイズを取得する方法を見つけることができませんでした。

+2

整数または浮動小数点数の配列に使用できる例については、http://stackoverflow.com/questions/25714086/swift-use-sizeof-with-int32-arrayを参照してください。しかし、 'String'構造体(固定サイズを持つ)は実際の文字ストレージへの不透明なポインタを含んでいるので、NSDataという配列の配列を単純に扱うことはできません。 –

+0

ありがとう@MartinR。だから、NSDataに文字列の配列を変換することは悪い考えです。不透明なポインタは何かもう少し説明できますか? – Andrej

+1

'struct String'には、「可視」APIの一部ではないメンバーがあります(ただし、デバッガで見ることができます)。これらのうちのいくつかは、文字列に使用される実際のストレージへのポインタです。 (例えば、同じ文字列は* storage *を共有することができます) - 要点は 'struct String'は自己完結型ではないということです。それをNSDataにパックし、別の場所に転送して展開すると、無効なポインタが含まれます。もちろん、文字列の配列からNSDataを作成することはできますが、各文字列(NUL終了UTF-8文字列など)を別々に追加する必要があります。 –

答えて

5

誤解のようです:各タイプTについて、すべてのインスタンス のTは、sizeof(T)として計算できる同じサイズを持っています。アレイの場合 、アレイ要素、 間パディングあり得る従ってarr1に必要な合計サイズが

arr1.count * strideof(Int) 

(例えばSwift: How to use sizeof?sizeof()strideof()の間の微妙な違いを比較)。

したがってアレイからNSDataを作成するための一般的な機能は、アレイがその要素に対して 連続するストレージを使用することwithUnsafeBufferPointer()保証を使用

extension Array { 
    func asData() -> NSData { 
     return self.withUnsafeBufferPointer({ 
      NSData(bytes: $0.baseAddress, length: count * strideof(Element)) 
     }) 
    } 
} 

あろう。 IntFloatのような "シンプル" タイプの場合

これは 期待される結果が得られます

let arr1 = [1, 2, 3] 
print(arr1.asData()) 
// <01000000 00000000 02000000 00000000 03000000 00000000> 

let arr2 = [1.0, 23556789000.0] 
print(arr2.asData()) 
// <00000000 0000f03f 0000204c 60f01542> 

をしかし、それは文字列の配列のために無用です:

let arr3 = ["hello", "ok", ""] 
print(arr3.asData()) 
// <945b2900 01000000 05000000 00000000 00000000 00000000 9a5b2900 01000000 02000000 00000000 00000000 00000000 068d2900 01000000 02000000 00000080 00000000 00000000> 

struct String理由実際の 文字記憶域への(隠された/文書化されていない)ポインタを含む。あるいは、

let data3 = NSMutableData() 
arr3.forEach { string in 
    string.withCString { 
     data3.appendBytes($0, length: Int(strlen($0)) + 1) 
    } 
} 
print(data3) 
// <68656c6c 6f006f6b 00f09f91 8d00> 

あなたが参照したスレッドのようにNSKeyedArchiverを使用します。

一つの可能​​性は、NUL終端 UTF-8文字列として各文字列を追加することです。

関連する問題