Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSCoder crash on decodeBool forKey (Xcode 8, Swift 3)

I have this simple class

import UIKit

class SimpleModel: NSObject, NSCoding {

    var name : String!
    var done : Bool!

    init(name:String) {
        self.name = name
        self.done = false
    }

    internal required init?(coder aDecoder: NSCoder) {
        self.name = aDecoder.decodeObject(forKey: "name") as! String
        self.done = aDecoder.decodeBool(forKey: "done") // BUG HERE
    }

    func encode(with encoder: NSCoder) {
        encoder.encode(self.name, forKey: "name")
        encoder.encode(self.done, forKey: "done")
    }
}

the save code:

let data = NSKeyedArchiver.archivedData(withRootObject: storageArray)
UserDefaults.standard.set(data, forKey: "storage")
UserDefaults.standard.synchronize()

the read code:

if let data = UserDefaults.standard.data(forKey: "storage") {
    storageArray = NSKeyedUnarchiver.unarchiveObject(with: data) as! [SimpleModel]
}

the problem occurs when the NSKeyedUnarchiver does it's job. I can not understand where the problem comes from.

Thanks!

like image 369
Enlil Avatar asked Aug 20 '16 12:08

Enlil


2 Answers

the trick is remove ! form the primitive types. If you put ! you are saying "make an implicit-unwrapped optional" so the encoder will archive as NSNumber instead of Bool (or Int, Double). If you remove ! the encoder will archive as Bool and things works as expected (I spent an "incident" and this solution is provided by Apple)

like image 182
Enlil Avatar answered Oct 05 '22 13:10

Enlil


Bool and Int have new methods:

 self.x = Int(decoder.decodeCInt(forKey: "Speed"))
 self.y = decoder.decodeObject(forKey: "Serial") as! String
 self.z = Bool(decoder.decodeBool(forKey: "Direction") )
like image 20
Sameer C Avatar answered Oct 05 '22 13:10

Sameer C