Создание массива в Swift из объекта NSData
Я пытаюсь сохранить массив целых чисел на диск в swift. Я могу получить их в объект NSData для хранения, но получить их обратно в массив сложно. Я могу получить raw COpaquePointer
данным с data.bytes
но не может найти способ инициализировать новый массив swift с помощью этого указателя. Кто-нибудь знает как это сделать?
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?
4 ответов
можно использовать getBytes
метод 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]
обновление для Swift 3 (Xcode 8): Swift 3 имеет новый тип struct Data
который является оберткой для NS(Mutable)Data
С правильной семантикой значений.
Методы доступа немного отличаются.
массив данных:
var arr: [UInt32] = [32, 4, UInt32.max]
let data = Data(buffer: UnsafeBufferPointer(start: &arr, count: arr.count))
print(data) // <20000000 04000000 ffffffff>
массив данных:
let arr2 = data.withUnsafeBytes {
Array(UnsafeBufferPointer<UInt32>(start: , count: data.count/MemoryLayout<UInt32>.stride))
}
print(arr2) // [32, 4, 4294967295]
Это также можно сделать с помощью UnsafeBufferPointer
, который по существу является "указателем массива", поскольку он реализует 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)
это устраняет необходимость инициализации пустого массива с дублированными элементами, чтобы затем перезаписать его, Хотя я понятия не имею, быстрее ли это. Как он использует Sequence
протокол это подразумевает итерацию, а не быструю копию памяти, хотя я не знаю, оптимизирован ли он при передаче указателя буфера. Опять же, я не уверен, как быстро" создать пустой массив с X идентичными элементами " инициализатор либо.
вот общий способ сделать это.
import Foundation
extension Data {
func elements <T> () -> [T] {
return withUnsafeBytes {
Array(UnsafeBufferPointer<T>(start: , 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
необходимо указать тип в array2
линии. В противном случае компилятор не может угадать.
Если вы имеете дело с данными в массиве (я точно знаю, что мой массив будет [String]), я вполне доволен этим:
NSKeyedUnarchiver.unarchiveObject (with: yourData)
надеюсь, это поможет