¿Cómo get el tamaño de bytes para una matriz arbitraria en Swift?

Me gustaría usar let rawDataFromArray = NSData(bytes: myArray, length: ???) , pero no sé cómo get la longitud de bytes para mi matriz. Aquí hay algunos ejemplos de lo que podría ser mi matriz:

 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 } 

No estoy seguro si revisar todos los elementos de la matriz (y en el caso de que las cadenas atraviesen cada carácter, ya que emojis podría tener más bytes que los representan) es la forma correcta de hacerlo.

¿Cómo get el tamaño de bytes para la matriz?
¿Podría alguien decirme la forma correcta de hacerlo?
O tal vez es solo que no es una buena práctica convertir Array a NSData en Swift?

También he visto la conversión de Swift Array a NSData para el almacenamiento persistente y la conversión de la matriz de bytes a NSData y la matriz personalizada a NSData , pero no podía encontrar la forma de get el tamaño de bytes para dicha matriz arbitraria.

Parece haber un malentendido: para cada tipo T , todas las instancias de T tienen el mismo tamaño que se puede calcular como tamaño de sizeof(T) . En el caso de matrices, puede haber un relleno entre los elementos de la matriz, por lo tanto, el tamaño total necesario para arr1 es

 arr1.count * strideof(Int) 

(Compare, por ejemplo, Swift: Cómo usar sizeof? Para las sutiles diferencias entre sizeof() y strideof() ).

Por lo tanto, una function genérica para crear NSData desde una matriz sería

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

Usar withUnsafeBufferPointer() garantiza que la matriz usa almacenamiento contiguo para sus elementos.

En el caso de types "simples" como Int y Float esto da los resultados esperados:

 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> 

Sin embargo, es inútil para una serie de cadenas:

 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> 

porque struct String contiene (ocultos / indocumentados) pointers al almacenamiento de caracteres real.

Una posibilidad sería anexar cada cadena como una cadena UTF-8 terminada en NUL:

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

Alternativamente, use NSKeyedArchiver como en los subprocesss a los que hizo reference.