ios - initialize - swift 4 declare array
Crear una matriz en Swift desde un objeto NSData (4)
Aquí hay una forma genérica de hacerlo.
import Foundation
extension Data {
func elements <T> () -> [T] {
return withUnsafeBytes {
Array(UnsafeBufferPointer<T>(start: $0, count: count/MemoryLayout<T>.size))
}
}
}
let array = [1, 2, 3]
let data = Data(buffer: UnsafeBufferPointer(start: array, count: array.count))
let array2: [Int] = data.elements()
array == array2
// IN THE PLAYGROUND, THIS SHOWS AS TRUE
Debe especificar el tipo en la línea array2
. De lo contrario, el compilador no puede adivinar.
Intento almacenar una matriz de enteros en el disco de forma rápida. Puedo ponerlos en un objeto NSData para almacenar, pero volverlos a poner en una matriz es difícil. Puedo obtener un COpaquePointer
sin COpaquePointer
para los datos con data.bytes
pero no puedo encontrar una manera de inicializar una nueva matriz rápida con ese puntero. Alguien sabe como hacerlo?
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?
Puede usar el método NSData
de 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]
Actualización para Swift 3 (Xcode 8): Swift 3 tiene un nuevo tipo struct Data
que es un contenedor para datos NS(Mutable)Data
con una semántica de valor adecuada. Los métodos de acceso son ligeramente diferentes.
Matriz a datos:
var arr: [UInt32] = [32, 4, UInt32.max]
let data = Data(buffer: UnsafeBufferPointer(start: &arr, count: arr.count))
print(data) // <20000000 04000000 ffffffff>
Datos para Matriz:
let arr2 = data.withUnsafeBytes {
Array(UnsafeBufferPointer<UInt32>(start: $0, count: data.count/MemoryLayout<UInt32>.stride))
}
print(arr2) // [32, 4, 4294967295]
Si está trabajando con Data to Array (estoy seguro de que mi matriz va a ser [String]), estoy bastante contento con esto:
NSKeyedUnarchiver.unarchiveObject (con: yourData)
Espero que ayude
También es posible hacerlo utilizando un UnsafeBufferPointer
, que es esencialmente un "puntero de matriz", ya que implementa el protocolo de Sequence
:
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)
Esto elimina la necesidad de inicializar un conjunto vacío con elementos duplicados primero, para luego sobrescribirlo, aunque no tengo idea de si es más rápido. Como utiliza el protocolo de Sequence
, esto implica una iteración en lugar de una copia de memoria rápida, aunque no sé si está optimizado cuando pasa un puntero de memoria intermedia. Por otra parte, tampoco estoy seguro de qué tan rápido sea el inicializador "crear una matriz vacía con X elementos idénticos".