12

Im trying to pass an array of 'Employee' objects iPhone to Apple Watch by serializing the array :

NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:employees];

and unserializing it as on the Watch side:

NSMutableArray *employees = [NSKeyedUnarchiver unarchiveObjectWithData:encodedObject];

This is the 'Employee' class:

@interface Employee : NSManagedObject
@property (nonatomic, retain) NSNumber * employeeID;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSNumber * age;
@property (nonatomic, retain) NSString * address;
@property (nonatomic, retain) NSString * designation;
@property (nonatomic, retain) NSString * teamName;
@property (nonatomic, retain) NSString * gender;
@property (nonatomic, retain) NSNumber * dateOfJoining;
@end

Do I have to do any changes on the Watch side to fix this error?

user2189878
  • 257
  • 3
  • 10
  • It looks like the code doing the decoding doesn't know about the `Employee` class. Is it being compiled into the watch side? – trojanfoe May 04 '16 at 12:50
  • Yes. I have to show list of Employees on the watch – user2189878 May 04 '16 at 12:53
  • make sure that Employee class added in the Watch target and it conforms NSCoding protocol. – Surya Subenthiran May 04 '16 at 14:47
  • Possible duplicate of [Can I encode a subclass of NSManagedObject?](http://stackoverflow.com/questions/1371749/can-i-encode-a-subclass-of-nsmanagedobject) –  May 04 '16 at 16:34
  • 1
    Do you realize that a managed object can't be passed to another thread, managed object context, or device? –  May 04 '16 at 16:46

3 Answers3

39

so I just had that exact same problem and the answer is simple but a little hard to find by oneself.

You simply have to use:

  • NSKeyedArchiver.setClassName("Employee", for: Employee.self)
    before serializing
  • NSKeyedUnarchiver.setClass(Employee.self, forClassName: "Employee")
    before deserializing

wherever needed.

Looks like iOS extensions prefix the class name with the extension's name.

Kendall Helmstetter Gelner
  • 74,769
  • 26
  • 128
  • 150
teriiehina
  • 4,741
  • 3
  • 41
  • 63
12

For me it was happening in my Today extension. What fixed it was adding @objc(MyExampleClass) before the declaration.

@objc(MyExampleClass)
open class MyExampleClass {
....
}
Stefan S
  • 721
  • 10
  • 13
2

teriiehina's answer got me part of the way there; I could archive and unarchive to clean devices but still got the above error when trying to unarchive an existing archive.

Eventually I found this question: Added a custom framework, now Swift can't unarchive data, which the user answered himself:

Moving DemoNote from the app to a framework did change the module name, which meant that NSKeyedUnarchiver couldn't find instances of the archived class due to a name mismatch.

His solution of prefixing the old project's name to the className string (e.g. if the project was called "CompanyDirectory" then using "CompanyDirectory.Employee" as opposed to just "Employee") was what I needed to be able to unarchive my data from my model which had been moved into a newly-created linked Framework.

tomg
  • 21
  • 3
  • You're right, archive/unarchive inside the same "context" (like inside the same app) works well without doing nothing. I had the problem archiving an object into the general pasteboard from App1 and unarchiving it getting the data from the pasteboard in App2. For this usecase I had to set the class as @teriiehina said. – DSoldo Nov 28 '19 at 09:24