I'm trying to store an array of integers to disk in swift. I can get them into an NSData object to store, but getting them back out into an array is difficult. I can get a raw COpaquePointer
to the data with data.bytes
but can't find a way to initialize a new swift array with that pointer. Does anyone know how to do it?
import Foundation var arr : UInt32[] = [32,4,123,4,5,2]; let data = NSData(bytes: arr, length: arr.count * sizeof(UInt32)) println(data) //data looks good in the inspector // now get it back into an array?
Array in swift is written as **Array < Element > **, where Element is the type of values the array is allowed to store. The type of the emptyArray variable is inferred to be [String] from the type of the initializer. The groceryList variable is declared as “an array of string values”, written as [String].
In Swift, creating a multi-dimensional array is just a matter of adding another set of brackets. For example, to turn our [String] array into an array of arrays, you would just write [[String]] .
To initialize a set with predefined list of unique elements, Swift allows to use the array literal for sets. The initial elements are comma separated and enclosed in square brackets: [element1, element2, ..., elementN] .
To create an empty string array in Swift, specify the element type String for the array and assign an empty array to the String array variable.
You can use the getBytes
method of NSData
:
// the number of elements: let count = data.length / sizeof(UInt32) // create array of appropriate length: var array = [UInt32](count: count, repeatedValue: 0) // copy bytes into array data.getBytes(&array, length:count * sizeof(UInt32)) print(array) // Output: [32, 4, 123, 4, 5, 2]
Update for Swift 3 (Xcode 8): Swift 3 has a new type struct Data
which is a wrapper for NS(Mutable)Data
with proper value semantics. The accessor methods are slightly different.
Array to Data:
var arr: [UInt32] = [32, 4, UInt32.max] let data = Data(buffer: UnsafeBufferPointer(start: &arr, count: arr.count)) print(data) // <20000000 04000000 ffffffff>
Data to Array:
let arr2 = data.withUnsafeBytes { Array(UnsafeBufferPointer<UInt32>(start: $0, count: data.count/MemoryLayout<UInt32>.stride)) } print(arr2) // [32, 4, 4294967295]
Update for Swift 5:
Array to Data:
let arr: [UInt32] = [32, 4, UInt32.max] let data = Data(buffer: UnsafeBufferPointer(start: arr, count: arr.count)) print(data) // <20000000 04000000 ffffffff>
Data to Array:
var arr2 = Array<UInt32>(repeating: 0, count: data.count/MemoryLayout<UInt32>.stride) _ = arr2.withUnsafeMutableBytes { data.copyBytes(to: $0) } print(arr2) // [32, 4, 4294967295]
It's also possible to do this using an UnsafeBufferPointer
, which is essentially an "array pointer", as it implements the Sequence
protocol:
let data = NSData(/* ... */) // Have to cast the pointer to the right size let pointer = UnsafePointer<UInt32>(data.bytes) let count = data.length / 4 // Get our buffer pointer and make an array out of it let buffer = UnsafeBufferPointer<UInt32>(start:pointer, count:count) let array = [UInt32](buffer)
This eliminates the need for initializing an empty array with duplicated elements first, to then overwrite it, although I have no idea if it's any faster. As it uses the Sequence
protocol this implies iteration rather than fast memory copy, though I don't know if it's optimized when passed a buffer pointer. Then again, I'm not sure how fast the "create an empty array with X identical elements" initializer is either.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With