swift3 xcode8 ios10

swift3 - NSKeyedArchiver no funciona en Swift 3(XCode 8)



xcode8 ios10 (4)

ACTUALIZACIÓN: Resolví este problema usando decodeInteger (forKey key: String) en lugar de decodeObject (forKey key: String). Por alguna razón, AnyObject no se convierte en Integer en Swift 3, aunque sí en Swift 2.2

He migrado mi proyecto a Swift 3 y NSKeyedArchiver no funciona. De hecho, tengo un error de tiempo de ejecución al intentar decodificar un objeto como este:

let startDayTime = aDecoder.decodeObject(forKey: Key.startDayTime) as! Int

Funcionó perfectamente en Swift 2.2 en Xcode 7.3. ¿Alguien más ha enfrentado tales problemas?

PS Tengo este error tanto en el simulador como en el dispositivo.

ACTUALIZACIÓN: decodeInteger(forKey key: String) este problema usando decodeInteger(forKey key: String) lugar de decodeObject(forKey key: String) . Por alguna razón, AnyObject no se convierte en Integer en Swift 3, aunque sí en Swift 2.2


Aquí está la solución:

class Person: NSObject, NSCoding { let name: String let age: Int required init(name: String, age: Int) { self.name = name self.age = age } required init(coder decoder: NSCoder) { self.name = decoder.decodeObject(forKey: "name") as? String ?? "" self.age = decoder.decodeInteger(forKey: "age") } func encode(with coder: NSCoder) { coder.encode(name, forKey: "name") coder.encode(age, forKey: "age") }}

Cómo utilizar:

class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let newPerson = Person(name: "Joe", age: 10) var people = [Person]() people.append(newPerson) let encodedData = NSKeyedArchiver.archivedData(withRootObject: people) UserDefaults.standard().set(encodedData, forKey: "people") if let data = UserDefaults.standard().data(forKey: "people"), myPeopleList = NSKeyedUnarchiver.unarchiveObject(with: data) as? [Person] { myPeopleList.forEach({print( $0.name, $0.age)}) // Joe 10 } else { print("There is an issue") } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() }}

Referencia: Swift 3 guardando y recuperando objetos personalizados de userDefaults


Parece que esto solo sucede en el límite de actualización de Swift 2 a Swift 3 cuando un blob NSData archivado con un NSKeyedArchiver en Swift 2 se abre con un NSKeyedUnarchiver en Swift 3. Mi opinión es que en Swift 2, Bool e Int están codificados como NSNumber , pero en Swift 3, están codificados como tipos Bool e Int sin Bool . Creo que la siguiente prueba apoya esta afirmación:

Esto funciona en Swift 3 para desarchivar un Bool codificado en Swift 2, pero devuelve nil si el Bool fue codificado en Swift 3:

let visible = aDecoder.decodeObject(forKey: "visible") as? Bool

Esto funciona en Swift 3 para desarchivar un Bool codificado en Swift 3, pero se bloquea si el Bool fue codificado en Swift 2:

let visible = aDecoder.decodeBool(forKey: "visible")

Mi solución es:

let visible = aDecoder.decodeObject(forKey: "visible") as? Bool ?? aDecoder.decodeBool(forKey: "visible")


Swift 3 :

Adopto el método del signo de interrogación doble ( ?? ) y funciona como un hechizo en una sola línea .

Si val no es nulo, se desempaqueta y se devuelve el valor. Si es nulo, aDecoder.decodeInteger(forKey: "val") devuelve:

self.val = aDecoder.decodeObject(forKey: "val") as? Int ?? aDecoder.decodeInteger(forKey: "val")