IvOS
IvOS

Reputation: 323

What is the best way to save and load an array of custom objects using swift?

I have an app that saves locations that a user provides by pressing on a map. The custom class looks like this:

class Places {
var name = ""
var latitude : CLLocationDegrees
var longitude : CLLocationDegrees

init(name: String, latitude: CLLocationDegrees, longitude:CLLocationDegrees) {

self.name = name
self.latitude = latitude
self.longitude = longitude
}

Then outside of the first viewController, a TableView, I set an empty array of these custom objects.

var places = [Places]()

On the next view controller, these objects are created after a long press on map.

var newPlace = Places(name: title, latitude: newCoordinate.latitude, longitude: newCoordinate.longitude)

            places.append(newPlace)

The app works well but nothing gets saved when it is closed. I tried saving the array to NSUserDefaults but apparently that can't be done with custom object arrays. What would be the most efficient way to save this array and then load it?

Upvotes: 0

Views: 1192

Answers (2)

Apple
Apple

Reputation: 123

I just implemented this into my program. I can't be certain it will work with var type CLLocationDegrees but I've done what you are trying to do with other variable types.

NSUser defaults should work but you have to put these in your class

class Places : NSObject, NSCoding {// Must inherit NSObject and implement NSCoding protocol

override init() {
    //must be empty initializer
}

//include all properties you want to store
required convenience init?(coder aDecoder: NSCoder) {
    self.init()
    self.name = aDecoder.decodeObjectForKey("name") as? String
    self.longitude = aDecoder.decodeObjectForKey("latitude") as? CLLocationDegrees
    self.latitude = aDecoder.decodeObjectForKey("longitude") as? CLLocationDegrees

}

//include all properties you want to load
func encodeWithCoder(aCoder: NSCoder) {

    aCoder.encodeObject(self.name, forKey: "name")
    aCoder.encodeObject(self.latitude, forKey: "latitude")
    aCoder.encodeObject(self.longitude, forKey: "longitude")
 }

When you want to save it.

let placesData = NSKeyedArchiver.archivedDataWithRootObject(places) //convert to NSdata
        NSUserDefaults.standardUserDefaults().setObject(placesData, forKey: "places") // required for array's / dicts of objects
        NSUserDefaults.standardUserDefaults().synchronize() // actual saving

Then when you want to use it

loadedPlaces = NSUserDefaults.standardUserDefaults().objectForKey("places") as? NSData {//grab data out of NSUserDefaults and convert it to NSData

        print("user has customized heroes")
        places = (NSKeyedUnarchiver.unarchiveObjectWithData(loadedPlaces) as? [Places])! // unarchive it from data to what it used to be

Upvotes: 1

Evgeny Sureev
Evgeny Sureev

Reputation: 1028

For this task I would choose NSCoding and NSKeyedArchive.

There are an article on NSHipster about different storage options discussing pros and cons of CoreData, NSUserDefaults and NSKeyedArchive with sample code for each method.

Upvotes: 1

Related Questions