I have been trying to figure out how to save an arrays of dictionaries using Enum types with NSCoding.
I have an enum with Medal types
enum Medal: String {
case Unearned = "NoMedal"
case Gold = "GoldMedal"
case Silver = "SilverMedal"
}
I have an array of dictionaries with the medal types in my GameData.swift class.
var medals: [[String: Medal]] = [
["1": .Unearned, "2": .Unearned, "3": .Unearned]
...
]
Than I have this code in the decoder method
convenience required init?(coder decoder: NSCoder) {
self.init()
medals = decoder.decodeObjectForKey(Key.medals) as? [[String: Medal]] ?? medals
}
and this is the encoder method which I believe is causing me the issues
// MARK: - Encode
func encodeWithCoder(encoder: NSCoder) {
encoder.encodeObject(medals as? AnyObject, forKey: Key.medals)
}
The problem is on a restart it is not saving/loading the medal array, it keeps resetting to default.
I have also tried this
encoder.encodeObject(medals as? [[String: Medal]], forKey: Key.medals)
and it causes a compiler error.
I also cannot use the regular syntax
encoder.encodeObject(medals, forKey: Key.medals)
Like I would for a array of dictionaries using normal values (e.g [String: Int]) as the compiler will also throw an error
medals is not an AnyObject, so when you encode it as? AnyObject you get nil.
Just because the enum has raw string values doesn't mean you can automatically bridge it to [String:String]. You have to do that yourself. For example (using Airspeed Velocity's version of mapValues):
convenience required init?(coder decoder: NSCoder) {
self.init()
if let medalStrings = decoder.decodeObjectForKey(Key.medals) as? [[String: String]] {
medals = medalStrings.map { $0.mapValues { Medal(rawValue: $0) ?? .Unearned } }
}
}
func encodeWithCoder(encoder: NSCoder) {
let medalStrings = medals.map { $0.mapValues { $0.rawValue } }
encoder.encodeObject(medalStrings, forKey: Key.medals)
}
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