How to save an array of objects to NSUserDefault with swift? How to save an array of objects to NSUserDefault with swift? ios ios

How to save an array of objects to NSUserDefault with swift?


Swift 4

We need to serialize our swift object to save it into userDefaults.

In swift 4 we can use Codable protocol, which makes our life easy on serialization and JSON parsing

Workflow(Save swift object in UserDefaults):

  1. Confirm Codable protocol to model class(class Place : Codable).
  2. Create object of class.
  3. Serialize that class using JsonEncoder class.
  4. Save serialized(Data) object to UserDefaults.

Workflow(Get swift object from UserDefaults):

  1. Get data from UserDefaults(Which will return Serialized(Data) object)
  2. Decode Data using JsonDecoder class

Swift 4 Code:

class Place: Codable {    var latitude: Double    var longitude: Double    init(lat : Double, long: Double) {        self.latitude = lat        self.longitude = long    }    public static func savePlaces(){        var placeArray = [Place]()        let place1 = Place(lat: 10.0, long: 12.0)        let place2 = Place(lat: 5.0, long: 6.7)        let place3 = Place(lat: 4.3, long: 6.7)        placeArray.append(place1)        placeArray.append(place2)        placeArray.append(place3)        let placesData = try! JSONEncoder().encode(placeArray)        UserDefaults.standard.set(placesData, forKey: "places")    }    public static func getPlaces() -> [Place]?{        let placeData = UserDefaults.standard.data(forKey: "places")        let placeArray = try! JSONDecoder().decode([Place].self, from: placeData!)        return placeArray    }}


From the Property List Programming Guide:

If a property-list object is a container (that is, an array or dictionary), all objects contained within it must also be property-list objects. If an array or dictionary contains objects that are not property-list objects, then you cannot save and restore the hierarchy of data using the various property-list methods and functions.

You'll need to convert the object to and from an NSData instance using NSKeyedArchiver and NSKeyedUnarchiver.

For example:

func savePlaces(){    let placesArray = [Place(lat: 123, lng: 123, name: "hi")]    let placesData = NSKeyedArchiver.archivedDataWithRootObject(placesArray)    NSUserDefaults.standardUserDefaults().setObject(placesData, forKey: "places")}func loadPlaces(){    let placesData = NSUserDefaults.standardUserDefaults().objectForKey("places") as? NSData    if let placesData = placesData {        let placesArray = NSKeyedUnarchiver.unarchiveObjectWithData(placesData) as? [Place]        if let placesArray = placesArray {            // do something…        }    }}


Swift 3 & 4

The following is the complete example code in Swift 3 & 4.

import Foundationclass Place: NSObject, NSCoding {    var latitude: Double    var longitude: Double    var name: String    init(latitude: Double, longitude: Double, name: String) {        self.latitude = latitude        self.longitude = longitude        self.name = name    }    required init?(coder aDecoder: NSCoder) {        self.latitude = aDecoder.decodeDouble(forKey: "latitude")        self.longitude = aDecoder.decodeDouble(forKey: "longitude")        self.name = aDecoder.decodeObject(forKey: "name") as? String ?? ""    }    func encode(with aCoder: NSCoder) {        aCoder.encode(latitude, forKey: "latitude")        aCoder.encode(longitude, forKey: "longitude")        aCoder.encode(name, forKey: "name")    }}func savePlaces() {    var placesArray: [Place] = []    placesArray.append(Place(latitude: 12, longitude: 21, name: "place 1"))    placesArray.append(Place(latitude: 23, longitude: 32, name: "place 2"))    placesArray.append(Place(latitude: 34, longitude: 43, name: "place 3"))    let placesData = NSKeyedArchiver.archivedData(withRootObject: placesArray)    UserDefaults.standard.set(placesData, forKey: "places")}func loadPlaces() {    guard let placesData = UserDefaults.standard.object(forKey: "places") as? NSData else {        print("'places' not found in UserDefaults")        return    }    guard let placesArray = NSKeyedUnarchiver.unarchiveObject(with: placesData as Data) as? [Place] else {        print("Could not unarchive from placesData")        return    }    for place in placesArray {        print("")        print("place.latitude: \(place.latitude)")        print("place.longitude: \(place.longitude)")        print("place.name: \(place.name)")    }}

 

Example Use:

savePlaces()loadPlaces()

 

Console Output:

place.latitude: 12.0place.longitude: 21.0place.name: 'place 1'place.latitude: 23.0place.longitude: 32.0place.name: 'place 2'place.latitude: 34.0place.longitude: 43.0place.name: 'place 3'