Guardar clase Swift personalizada con NSCoding en UserDefaults
Actualmente estoy intentando guardar una clase Swift personalizada en NSUserDefaults. Aquí está el código de mi Playground:
import Foundation
class Blog : NSObject, NSCoding {
var blogName: String?
override init() {}
required init(coder aDecoder: NSCoder) {
if let blogName = aDecoder.decodeObjectForKey("blogName") as? String {
self.blogName = blogName
}
}
func encodeWithCoder(aCoder: NSCoder) {
if let blogName = self.blogName {
aCoder.encodeObject(blogName, forKey: "blogName")
}
}
}
var blog = Blog()
blog.blogName = "My Blog"
let ud = NSUserDefaults.standardUserDefaults()
ud.setObject(blog, forKey: "blog")
Cuando ejecuto el código, aparece el siguiente error
La ejecución fue interrumpida, motivo: señal SIGABRT.
en la última línea ( ud.setObject
...)
El mismo código también falla cuando está en una aplicación con el mensaje
"La lista de propiedades no es válida para el formato: 200 (las listas de propiedades no pueden contener objetos del tipo 'CFType')"
¿Alguien puede ayudar? Estoy usando Xcode 6.0.1 en Maverick. Gracias.
En Swift 4 o superior, use codificable.
En su caso, utilice el siguiente código.
class Blog: Codable {
var blogName: String?
}
Ahora crea su objeto. Por ejemplo:
var blog = Blog()
blog.blogName = "My Blog"
Ahora codificalo así:
if let encoded = try? JSONEncoder().encode(blog) {
UserDefaults.standard.set(encoded, forKey: "blog")
}
y decodificarlo así:
if let blogData = UserDefaults.standard.data(forKey: "blog"),
let blog = try? JSONDecoder().decode(Blog.self, from: blogData) {
}
El primer problema es que debes asegurarte de tener un nombre de clase que no esté alterado:
@objc(Blog)
class Blog : NSObject, NSCoding {
Luego debe codificar el objeto (en un NSData) antes de poder almacenarlo en los valores predeterminados del usuario:
ud.setObject(NSKeyedArchiver.archivedDataWithRootObject(blog), forKey: "blog")
De manera similar, para restaurar el objeto necesitarás desarchivarlo:
if let data = ud.objectForKey("blog") as? NSData {
let unarc = NSKeyedUnarchiver(forReadingWithData: data)
unarc.setClass(Blog.self, forClassName: "Blog")
let blog = unarc.decodeObjectForKey("root")
}
Ten en cuenta que si no lo estás usando en el patio de recreo es un poco más sencillo ya que no tienes que registrar la clase manualmente:
if let data = ud.objectForKey("blog") as? NSData {
let blog = NSKeyedUnarchiver.unarchiveObjectWithData(data)
}