arrays swift serialization nscoding

arrays - ¿Cómo puedo obtener un NSCoder para codificar/decodificar una serie de estructuras Swift?



serialization nscoding (1)

Aquí hay una posible solución que codifica la matriz UInt64 como una matriz de bytes. Está inspirado en las respuestas a ¿Cómo serializar la matriz C con NSCoding? .

class MyObject: NSObject, NSCoding { var values: [UInt64] = [] init(values : [UInt64]) { self.values = values } // MARK: - NSCoding required init(coder decoder: NSCoder) { super.init() var count = 0 // decodeBytesForKey() returns an UnsafePointer<UInt8>, pointing to immutable data. let ptr = decoder.decodeBytesForKey("values", returnedLength: &count) // If we convert it to a buffer pointer of the appropriate type and count ... let buf = UnsafeBufferPointer<UInt64>(start: UnsafePointer(ptr), count: count/sizeof(UInt64)) // ... then the Array creation becomes easy. values = Array(buf) } func encodeWithCoder(coder: NSCoder) { // This encodes both the number of bytes and the data itself. coder.encodeBytes(UnsafePointer(values), length: values.count * sizeof(UInt64), forKey: "values") } }

Prueba:

let obj = MyObject(values: [1, 2, 3, UInt64.max]) let data = NSKeyedArchiver.archivedDataWithRootObject(obj) let dec = NSKeyedUnarchiver.unarchiveObjectWithData(data) as! MyObject print(dec.values) // [1, 2, 3, 18446744073709551615]

Actualización para Swift 3 (Xcode 8):

class MyObject: NSObject, NSCoding { var values: [UInt64] = [] init(values : [UInt64]) { self.values = values } // MARK: - NSCoding required init(coder decoder: NSCoder) { super.init() var count = 0 // decodeBytesForKey() returns an UnsafePointer<UInt8>?, pointing to immutable data. if let ptr = decoder.decodeBytes(forKey: "values", returnedLength: &count) { // If we convert it to a buffer pointer of the appropriate type and count ... let numValues = count / MemoryLayout<UInt64>.stride ptr.withMemoryRebound(to: UInt64.self, capacity: numValues) { let buf = UnsafeBufferPointer<UInt64>(start: UnsafePointer($0), count: numValues) // ... then the Array creation becomes easy. values = Array(buf) } } } public func encode(with coder: NSCoder) { // This encodes both the number of bytes and the data itself. let numBytes = values.count * MemoryLayout<UInt64>.stride values.withUnsafeBufferPointer { $0.baseAddress!.withMemoryRebound(to: UInt8.self, capacity: numBytes) { coder.encodeBytes($0, length: numBytes, forKey: "values") } } } } let obj = MyObject(values: [1, 2, 3, UInt64.max]) let data = NSKeyedArchiver.archivedData(withRootObject: obj) let dec = NSKeyedUnarchiver.unarchiveObject(with: data) as! MyObject print(dec.values) // [1, 2, 3, 18446744073709551615]

Tengo un objeto que debe ajustarse a NSCoding y que contiene una matriz de valores UInt64 . ¿Cómo puedo codificar / decodificar con un NSCoder en absoluto? Pregunta extra: ¿cómo puedo codificarlo de forma más compacta? (Tiene que ir a los datos de estado de Game Center guardados, cuyo tamaño es limitado).

Idealmente, solo quiero escribir un Int que tenga el tamaño n de la matriz, y luego escribir n veces los 64 bits de un UInt64 , y leerlo de manera similar. ¿Puedo hacer esto?

coder.encodeObject(values, forKey: "v") no funciona.

class MyObject: NSCoding { private var values: [UInt64] // … // MARK: - NSCoding required init(coder decoder: NSCoder) { // ??? } func encodeWithCoder(coder: NSCoder) { // ??? } }