How to get byte size for an arbitrary array in Swift?

I would like to use let rawDataFromArray = NSData(bytes: myArray, length: ???) , but I don't know how to get the byte length for my array. Here are some examples of what might be with my array:

 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 } 

I'm not sure if going through each element of the array (and in the case of strings passing through each character, since emojis can have more bytes representing them) is the right way to do this.

How to get byte size for an array?
Can someone tell me the correct way to do this?
Or maybe it's just that it is not recommended to translate Array to NSData in Swift?

I also saw Convert Swift Array to NSData for persistent storage and Convert a byte array to NSData a> and Custom Array to NSData , but could not figure out how to get the byte size for such an arbitrary array.

+5
source share
1 answer

There seems to be a misunderstanding: for each type T all instances of T have the same size that can be calculated as sizeof(T) . In the case of arrays, there may be indents between the elements of the array, so the total size required for arr1 is

 arr1.count * strideof(Int) 

(Compare, for example, Swift: how to use sizeof? For subtle differences between sizeof() and strideof() ).

Therefore, the general function for creating NSData from an array will be

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

Using withUnsafeBufferPointer() ensures that the array uses continuous storage for its elements.

In the case of "simple" types such as Int and Float , this gives the expected results:

 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> 

However, this is useless for an array of strings:

 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> 

since struct String contains (hidden / undocumented) pointers to the actual storage of characters.

One possibility is to add each line as a NUL-terminated UTF-8 String:

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

Alternatively, use NSKeyedArchiver , as in the streams you referenced.

+5
source

Source: https://habr.com/ru/post/1236313/


All Articles