unrecognized selector sent to instance calling NSCoder.encode()

I'm trying to save an array of objects using NSKeyedArchiver. My objects look like


class Site: NSObject, MKAnnotation

{

var coordinate: CLLocationCoordinate2D

var fOwnerID: String

var fType: SiteType

var fIcon: String

}

and I'm trying to encode the array like this:

for idx in 0..<fSiteN

{

aCoder.encode(fSites[idx], forKey: "fSites_\(idx)")

}


but I get the unrecognized selecter error, so I clearly don't understand how this works.

So how is this done? Any help greatly appreciated.

Steve.

Accepted Answer

Is the "fSites" variable an array of "Site" instances? If so then class Site must conform to NSCoding too. That is, the class must know how to encode/decode its own instance variables.

You can encode the array in one shot (if its items are encodable), no need to encode index by index


aCoder.encode(fSites, forKey: "fSites")


You will decode


self.fSites        = decoder.decodeObjectForKey("fSites") as? Array<Site>


2 advices :

- give more readable names to you var. For instance, it's better to name numberOfSites than fSiteN ; avoid prefix like f unless they are really meaningful to you

- for the keys, declare them as local constants to avoid mistyping (compiler will not detect and you would get execution error

let sitesKey = "fSites"

Many Thanks

Please ignore this reply. I found the solution myself, which was to use decodeDouble() instead of decodeObject() to decode location co-ordinates.


Actually, I'm still stuck 😕

So here's what I have now:


The basic object that I want to save an array of looks like this ...


class Site: NSObject, NSCoding, MKAnnotation

{

var coordinate = CLLocationCoordinate2D(latitude:0, longitude:0)

var fOwnerID = ""

var fIcon = ""

var fDate = Date()


override init()

{

}


required convenience init(coder aDecoder: NSCoder)

{

let latitude = aDecoder.decodeObject(forKey: "latitude") as? CLLocationDegrees

let longitude = aDecoder.decodeObject(forKey: "longitude") as? CLLocationDegrees

let owner = aDecoder.decodeObject(forKey: "fOwnerID") as? String

let icon = aDecoder.decodeObject(forKey: "fIcon") as? String

let dtim = aDecoder.decodeObject(forKey: "fDate") as? Date

self.init()


self.coordinate = CLLocationCoordinate2D(latitude:latitude!, longitude:longitude!)

self.fOwnerID = owner!

self.fIcon = icon!

self.fDate = dtim!

}


func encode(with aCoder: NSCoder)

{

aCoder.encode(coordinate.latitude, forKey: "latitude")

aCoder.encode(coordinate.longitude, forKey: "longitude")

aCoder.encode(fOwnerID, forKey: "fOwnerID")

aCoder.encode(fIcon, forKey: "fIcon")

aCoder.encode(fDate, forKey: "fDate")

}

}


... while the object containing the array encodes it like this ...


aCoder.encode(fSites, forKey: "fSites")


... and decodes it like this ...


self.fSites = (aDecoder.decodeObject(forKey: "fSites") as? [Site])!


... but I get an "unexpectedly found nil while unwrapping an Optional value" when trying to construct the coordinate. According to the documentation, decodeObject only returns nil if either the key or its value is nil, but perhaps the cast to CLLocationDegrees is the problem (?) The latter is required to prevent an error in the initializer for a CLLocationCoordinate2D.


Thanks again in advance for your ongoing assistance with these issues.

Steve.

unrecognized selector sent to instance calling NSCoder.encode()
 
 
Q