this is a class Place
I defined:
class Place: NSObject { var latitude: Double var longitude: Double init(lat: Double, lng: Double, name: String){ self.latitude = lat self.longitude = lng } required init(coder aDecoder: NSCoder) { self.latitude = aDecoder.decodeDoubleForKey("latitude") self.longitude = aDecoder.decodeDoubleForKey("longitude") } func encodeWithCoder(aCoder: NSCoder!) { aCoder.encodeObject(latitude, forKey: "latitude") aCoder.encodeObject(longitude, forKey: "longitude") } }
This is how I tried to save an array of Place
s:
var placesArray = [Place] //... func savePlaces() { NSUserDefaults.standardUserDefaults().setObject(placesArray, forKey: "places") println("place saved") }
It didn't work, this is what I get on the console:
Property list invalid for format: 200 (property lists cannot contain objects of type 'CFType')
I am new to iOS, could you help me ?
SECOND EDITION
I found a solution to save the data :
func savePlaces(){ let myData = NSKeyedArchiver.archivedDataWithRootObject(placesArray) NSUserDefaults.standardUserDefaults().setObject(myData, forKey: "places") println("place saved") }
But I get an error when loading the data with this code :
let placesData = NSUserDefaults.standardUserDefaults().objectForKey("places") as? NSData if placesData != nil { placesArray = NSKeyedUnarchiver.unarchiveObjectWithData(placesData!) as [Place] }
the error is :
[NSKeyedUnarchiver decodeDoubleForKey:]: value for key (latitude) is not a double number'
I am pretty sure I archived a Double, there is an issue with the saving/loading process
Any clue ?
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.
To store the string in the user's defaults database, which is nothing more than a property list or plist, we pass the string to the set(_:forKey:) method of the UserDefaults class. We also need to pass a key as the second argument to the set(_:forKey:) method because we are creating a key-value pair.
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):
Workflow(Get swift object from UserDefaults):
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… } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With