nscoding swift3 xcode8 ios10

nscoding - Swift 3 guardando y recuperando objetos personalizados de userDefaults



swift3 xcode8 (4)

Prueba esto:

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

Tengo esto en Playground usando Swift 3, Xcode 8.0:

import Foundation class Person: NSObject, NSCoding { var name: String var age: Int init(name: String, age: Int) { self.name = name self.age = age } required convenience init(coder aDecoder: NSCoder) { let name = aDecoder.decodeObject(forKey: "name") as! String let age = aDecoder.decodeObject(forKey: "age") as! Int self.init( name: name, age: age ) } func encode(with aCoder: NSCoder) { aCoder.encode(name, forKey: "name") aCoder.encode(age, forKey: "age") } }

crear una matriz de persona

let newPerson = Person(name: "Joe", age: 10) var people = [Person]() people.append(newPerson)

codificar la matriz

let encodedData = NSKeyedArchiver.archivedData(withRootObject: people) print("encodedData: /(encodedData))")

guardar en valores predeterminados del usuario

let userDefaults: UserDefaults = UserDefaults.standard() userDefaults.set(encodedData, forKey: "people") userDefaults.synchronize()

cheque

print("saved object: /(userDefaults.object(forKey: "people"))")

retirarse de los valores predeterminados del usuario

if let data = userDefaults.object(forKey: "people") { let myPeopleList = NSKeyedUnarchiver.unarchiveObject(with: data as! Data) print("myPeopleList: /(myPeopleList)") }else{ print("There is an issue") }

solo verifique los datos archivados

if let myPeopleList = NSKeyedUnarchiver.unarchiveObject(with: encodedData){ print("myPeopleList: /(myPeopleList)") }else{ print("There is an issue") }

No puedo guardar correctamente el objeto de datos en userDefaults, y además, la verificación en la parte inferior crea el error "error fatal: inesperadamente encontrado nulo al desenvolver un valor Opcional". La línea de "verificación" también muestra que el objeto guardado es nulo. ¿Es este un error en el NSCoder de mi objeto?


En Swift 4:

Puede usar Codificable para guardar y recuperar objetos personalizados de los valores predeterminados del usuario. Si lo hace con frecuencia, puede agregarlo como extensión y usarlo como se muestra a continuación.

extension UserDefaults { func save<T:Encodable>(customObject object: T, inKey key: String) { let encoder = JSONEncoder() if let encoded = try? encoder.encode(object) { self.set(encoded, forKey: key) } } func retrieve<T:Decodable>(object type:T.Type, fromKey key: String) -> T? { if let data = self.data(forKey: key) { let decoder = JSONDecoder() if let object = try? decoder.decode(type, from: data) { return object }else { print("Couldnt decode object") return nil } }else { print("Couldnt find key") return nil } } }

Su clase debe seguir Codificable. Es solo un tipo para el protocolo codificable y decodificable.

class UpdateProfile: Codable { //Your stuffs }

Uso:

let updateProfile = UpdateProfile() //To save the object UserDefaults.standard.save(customObject: updateProfile, inKey: "YourKey") //To retrieve the saved object let obj = UserDefaults.standard.retrieve(object: UpdateProfile.self, fromKey: "YourKey")

Para obtener más tipos personalizados de codificación y decodificación, consulte la documentación de Apple .


Swift 4 Note

Una vez más, puede guardar / probar sus valores en un área de juegos

Swift 3

Los valores predeterminados del usuario deben probarse en un proyecto real. Nota: No es necesario forzar la sincronización. Si desea probar la codificación / decodificación en un patio de recreo, puede guardar los datos en un archivo plist en el directorio de documentos utilizando el archivador con clave. También debe solucionar algunos problemas en su clase:

class Person: NSObject, NSCoding { let name: String let age: Int 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") } }

Pruebas:

class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // setting a value for a key 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") // retrieving a value for a key if let data = UserDefaults.standard.data(forKey: "people"), let myPeopleList = NSKeyedUnarchiver.unarchiveObject(with: data) as? [Person] { myPeopleList.forEach({print( $0.name, $0.age)}) // Joe 10 } else { print("There is an issue") } } }


let age = aDecoder.decodeObject(forKey: "age") as! Int

Esto se ha cambiado para Swift 3; esto ya no funciona para los tipos de valor. La sintaxis correcta es ahora:

let age = aDecoder.decodeInteger(forKey: "age")

Hay funciones decodificadas ... () asociadas para varios tipos diferentes:

let myBool = aDecoder.decodeBoolean(forKey: "myStoredBool") let myFloat = aDecoder.decodeFloat(forKey: "myStoredFloat")

Editar: Lista completa de todas las posibles funciones de decodeXXX en Swift 3

Editar:

Otra nota importante: si ha guardado previamente datos que fueron codificados con una versión anterior de Swift, esos valores deben decodificarse usando decodeObject (), sin embargo , una vez que vuelva a codificar los datos usando codificar (...) ya no podrá ser decodificado con decodeObject () si es un tipo de valor. Por lo tanto, la respuesta de Markus Wyss le permitirá manejar el caso en que los datos se codificaron utilizando cualquiera de las versiones de Swift:

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