Search code examples
swiftnscoding

How to implement NSCoding


import Foundation

class C: NSObject, NSCoding {
    var n: String = ""

    override init() {
        super.init()
        n = "instance of class C"
    }

    convenience init(_ name: String) {
        self.init()
        n = name
    }

    required init(coder: NSCoder) {
        // self.init()
        // super.init()
        // super.init(coder)
        n = coder.decodeObjectForKey("name") as String
    }

    func encodeWithCoder(coder: NSCoder) {
        coder.encodeObject(n, forKey:"name")
    }

    override var description: String {
        get { return "C instance: \(n)" }
    }
}

let c = C("Tom")
println(c)
if NSKeyedArchiver.archiveRootObject(c, toFile: "demo") {
    println("OK")
}
let c2: C = NSKeyedUnarchiver.unarchiveObjectWithFile("demo") as C

Compiled on the command line with

xcrun swift coder.swift

The call NSKeyedUnarchiver.unarchiveObjectWithFile fails, crashing with this

> xcrun swift coder.swift
C instance: Tom
OK
2014-09-06 10:45:11.925 swift[483:100b] *** Terminating app due to uncaught exception
'NSInvalidUnarchiveOperationException', reason: '*** -[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (coder.C)'

I've looked at various "working examples" but they don't seem to work for me. None of the commented lines work or help. What am I doing wrong?


Solution

  • I recommend opening a radar (bugreport.apple.com). This works fine if you compile it rather than trying to run it directly via the swift interpretter. It works in Xcode. It works in playgrounds. It works with xcrun -sdk macosx swiftc coder.swift && ./coder. The only case where it does not work is via swift.