Cannot decode object of class
ios, swift, watchkit
Solution
NOTE: While the information in this answer is correct, the way better answer is the one below by @agy.
This is caused by the compiler creating `MyApp.Person` & `MyAppWatchKitExtension.Person` from the same class. It's usually caused by sharing the same class across two targets instead of creating a framework to share it.
Two fixes:
The proper fix is to extract `Person` into a framework. Both the main app & watchkit extension should use the framework and will be using the same `*.Person` class.
The workaround is to serialize your class into a Foundation object (like `NSDictionary`) before you save & pass it. The `NSDictionary` will be code & decodable across both the app and extension. A good way to do this is to implement the `RawRepresentable` protocol on `Person` instead.
Problem
I am trying to send a "Class" to my Watchkit extension but I get this error. * Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: '* -[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (MyApp.Person) Archiving and unarchiving works fine on the iOS App but not while communicating with the watchkit extension. What's wrong? InterfaceController.swift ``` let userInfo = ["method":"getData"] WKInterfaceController.openParentApplication(userInfo, reply: { (userInfo:[NSObject : AnyObject]!, error: NSError!) -> Void in println(userInfo["data"]) // prints <62706c69 7374303... if let data = userInfo["data"] as? NSData { if let person = NSKeyedUnarchiver.unarchiveObjectWithData(data) as? Person { println(person.name) } } }) ``` AppDelegate.swift ``` func application(application: UIApplication!, handleWatchKitExtensionRequest userInfo: [NSObject : AnyObject]!, reply: (([NSObject : AnyObject]!) -> Void)!) { var bob = Person() bob.name = "Bob" bob.age = 25 reply(["data" : NSKeyedArchiver.archivedDataWithRootObject(bob)]) return } ``` Person.swift ``` class Person : NSObject, NSCoding { var name: String! var age: Int! // MARK: NSCoding required convenience init(coder decoder: NSCoder) { self.init() self.name = decoder.decodeObjectForKey("name") as! String? self.age = decoder.decodeIntegerForKey("age") } func encodeWithCoder(coder: NSCoder) { coder.encodeObject(self.name, forKey: "name") coder.encodeInt(Int32(self.age), forKey: "age") } } ```