我想使用let rawDataFromArray = NSData(bytes: myArray, length: ???)
,但不知道如何获取数组的字节长度。以下是我的数组可能是什么的一些例子:
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中将Array
转换为NSData
并不是一个好习惯?
我还看过Converting Swift Array to NSData for persistent storage和Converting array of bytes to NSData以及Custom Array to NSData,但无法弄清楚如何为这种任意数组获取字节大小。
答案 0 :(得分:5)
似乎存在误解:对于每种类型T
,所有实例
T
的大小相同,可以计算为sizeof(T)
。
对于数组,数组元素之间可以有填充,
因此arr1
所需的总大小为
arr1.count * strideof(Int)
(例如Swift: How to use sizeof?比较sizeof()
和strideof()
之间的微妙差异。
因此,从数组创建NSData
的通用函数将是
extension Array {
func asData() -> NSData {
return self.withUnsafeBufferPointer({
NSData(bytes: $0.baseAddress, length: count * strideof(Element))
})
}
}
使用withUnsafeBufferPointer()
保证数组使用
其元素的连续存储。
对于像Int
和Float
这样的“简单”类型,这样就可以了
预期结果:
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
包含指向实际的(隐藏/未记录的)指针
字符存储。
一种可能性是将每个字符串附加为NUL终止 UTF-8字符串:
let data3 = NSMutableData()
arr3.forEach { string in
string.withCString {
data3.appendBytes($0, length: Int(strlen($0)) + 1)
}
}
print(data3)
// <68656c6c 6f006f6b 00f09f91 8d00>
或者,在您引用的线程中使用NSKeyedArchiver
。