Save custom class objects in NSUserDefaults in Swift

3.5k views Asked by At

Im trying to save some objects in an array but my objects are used inherited properties But when trying to read the object it says

  Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -decodeObjectForKey: cannot be sent to an abstract object of class NSCoder: Create a concrete instance!'

The structure is

Service(SuperClass)
      Service1(Subclass)
      Service2
      Service3

In this way im using this code

var S1:Service1 = Service1()
        S1.apiKey = Apikey.text!
        TableViewController.agregar(S1)
        let datos = NSKeyedArchiver.archivedDataWithRootObject(TableViewController.Servicios!)
        NSUserDefaults.standardUserDefaults().setObject(datos, forKey: "ServiciosGuardados")
        NSUserDefaults.standardUserDefaults().synchronize()

And this is the classes functions

class Servicio:NSObject, NSCoding{
var nombre:String = "null"
var tipo:Int = 0

override init() {}

required init(coder aDecoder: NSCoder = NSCoder.empty()) {
    self.nombre = aDecoder.decodeObjectForKey("nombre") as! String
    self.tipo = aDecoder.decodeObjectForKey("tipo") as! Int
}
func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeObject(nombre, forKey: "nombre")
    aCoder.encodeObject(tipo, forKey: "tipo")
}

-My problem is in here in Service1 which inherites from Servicio

class Service1: Servicio {
var apiKey = "null"


override init() {
    super.init(coder: NSCoder())
}

required init(coder aDecoder: NSCoder) {
    super.init(coder: NSCoder())
    if let apiKey = aDecoder.decodeObjectForKey("apiKey") as? String {
        self.apiKey = apiKey
    }
}

override func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeObject(self.apiKey, forKey: "apiKey")
}
2

There are 2 answers

1
Ashish Kakkad On

Here is :

Storable Types in NSUserDefaults

The NSUserDefaults class acts very much like something called a Property List (aka plist). It may be just a fancy interface for a plist, or it may be more, I’m not entirely sure. Nonetheless, plists are limited in what kind of objects they can store. The six types plists can store are:

NSData
NSString
NSNumber
NSDate
NSArray
NSDictionary

Here is obj-c example to store custom objects : How to store custom objects in NSUserDefaults

0
Eric Aya On

You can't use NSUserDefaults to save objects that are not of type NSData, NSString, NSNumber, NSDate, NSArray or NSDictionary.

But you can serialize and save/load your custom objects in a file thanks to NSCoding.

Since your class already supports NSCoding, use NSKeyedArchiver and NSKeyedUnarchiver to store and retrieve your custom objects:

// save your custom object in a file
NSKeyedArchiver.archiveRootObject(myCustomObject, toFile: "/path/to/filename")

// load your custom object from the file
if let temp = NSKeyedUnarchiver.unarchiveObjectWithFile("/path/to/filename") {
    self.myCustomObject = temp
}

In this example, myCustomObject could be a Service1 instance, or an array of instances, etc.