Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use NSUserDefaults to store an array of custom classes in Swift?

I have a custom class called Person that stores various attributes about someone when they enter information.

class Person {

    // Person dictionary variable
    var name: String?
    var age: String?
    var html_url: String?

    init(json: NSDictionary) { // Dictionary object
        self.name = json["name"] as? String
        self.age = json["age"] as? String
        self.html_url = json["html_url"] as? String // Location of the JSON file
    }
}

Once the dictionary is created, it is then placed into an array. I am having problems saving the array into NSUserDefaults when a button is tapped.

personArray.append(newPerson) // newPerson = dictionary of attributes


NSUserDefaults.standardUserDefaults().setObject(personArray, forKey: "personArray")
        NSUserDefaults.standardUserDefaults().synchronize()

I have had a look at How to store custom objects in NSUserDefaults and Saving custom SWIFT class with NSCoding to UserDefaults but I have had no luck and am finding it hard to understand.

I when I simply try to save into NSUserDefaults, I am told the following:

Attempt to set a non-property-list object (
    "PersonApp.Person"
) as an NSUserDefaults/CFPreferences value for key personArray

Would anyone be able to help me actually save an array of custom objects (custom dictionaries) via NSUserDefaults?

like image 543
Daniel Bramhall Avatar asked Jul 27 '16 08:07

Daniel Bramhall


1 Answers

Your Person class should look like this:

Swift 3:

class Person : NSObject, NSCoding{

    // Person dictionary variable
    var name: String?
    var age: String?
    var html_url: String?

    init(json: NSDictionary) { // Dictionary object
        self.name = json["name"] as? String
        self.age = json["age"] as? String
        self.html_url = json["html_url"] as? String // Location of the JSON file
    }

    required init?(coder aDecoder: NSCoder) {

        self.name = aDecoder.decodeObjectForKey("name") as? String;
        self.age = aDecoder.decodeObjectForKey("age") as? String;
        self.html_url = aDecoder.decodeObjectForKey("html") as? String;
    }

    func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeObject(self.name, forKey: "name");
        aCoder.encodeObject(self.age, forKey: "age");
        aCoder.encodeObject(self.html_url, forKey: "html");
    }
}

And here you have an example of saving and retrieving the array from NSUserDefaults:

let p = Person()
p.name = "person1"
p.age = "12"
p.html_url = "www.google.ro"

let p2 = Person()
p2.name = "person2"
p2.age = "11"
p2.html_url = "www.google.ro"

let array = [p, p2]

let userDefaults = NSUserDefaults.standardUserDefaults()
userDefaults.setValue(NSKeyedArchiver.archivedDataWithRootObject(array), forKey: "persons")
userDefaults.synchronize()

let array : [Person]
array = NSKeyedUnarchiver.unarchiveObjectWithData(userDefaults.objectForKey("persons") as! NSData) as! [Person]
print("\(array[0].name)\(array[1].name)")

Swift 4:

class Person : NSObject, NSCoding{

    // Person dictionary variable
    var name: String?
    var age: String?
    var html_url: String?

    init(json: NSDictionary) { // Dictionary object
        self.name = json["name"] as? String
        self.age = json["age"] as? String
        self.html_url = json["html_url"] as? String // Location of the JSON file
    }

    required init?(coder aDecoder: NSCoder) {
        self.name = aDecoder.decodeObject(forKey: "name") as? String;
        self.age = aDecoder.decodeObject(forKey: "age") as? String;
        self.html_url = aDecoder.decodeObject(forKey: "html") as? String;
    }

    func encode(with aCoder: NSCoder) {
        aCoder.encode(self.name, forKey: "name");
        aCoder.encode(self.age, forKey: "age");
        aCoder.encode(self.html_url, forKey: "html");
    }
}
like image 138
vbgd Avatar answered Sep 21 '22 12:09

vbgd