I'm getting the following exception when trying to unarchive when using Swift:
Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: '*** -[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (NSKnownKeysDictionary1) for key (NS.objects); the class may be defined in source code or a library that is not linked'
The context: I'm creating a "Share Links" extension. In my main app (written in Objective C) I write out an array of dictionaries with the information about the links using MMWormhole.
NSFetchRequest* bookmarkFetch = [NSFetchRequest fetchRequestWithEntityName:@"XX"];
bookmarkFetch.propertiesToFetch = @[
@"name", @"text", @"date", @"url"
];
bookmarkFetch.resultType = NSDictionaryResultType;
NSArray* bookmarks = [moc executeFetchRequest:bookmarkFetch error:NULL];
[wormhole passMessageObject:bookmarks identifier:@"XXX"];
The values in the array are NSStrings and an NSDate.
In the bowels of MMWormhole you get:
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:messageObject];
messageObject is just the bookmarks array without any intermediate processing.
In the extension I have:
let wormhole = MMWormhole(applicationGroupIdentifier: "group.XX", optionalDirectory:nil)
let bookmarks = wormhole.messageWithIdentifier("XXX") as? Array<Dictionary<String,AnyObject>>
messageWithIdentifier: ends up calling this ultimately:
id messageObject = [NSKeyedUnarchiver unarchiveObjectWithData:data];
The array is written out to the app group folder correctly -- I can read it using another extension, one written in Objective C.
This exception appears when I run in the Simulator. The code appears to work correctly when run on a 32-bit device (iPhone 5 and iPad 3). I don't have a 64-bit device to test on currently.
I imagine I'm missing an import
or a framework, but which one(s)?
This is just a side note:
You can set class names for both the NSKeyedArchiver
& NSKeyedUnarchiver
.
I had this problem without dealing with CoreData at all. The unarchiver did not find my own class anymore.
Setting the className
for my class works as shown below:
For the archiver
:
NSKeyedArchiver.setClassName("MyClass", for: MyClass.self)
let data = NSKeyedArchiver.archivedData(withRootObject: root)
And the unarchiver
:
NSKeyedUnarchiver.setClass(MyClass.self, forClassName: "MyClass")
let root = NSKeyedUnarchiver.unarchiveObject(with: data)
I asked this on the Apple Developer forums and (for once) got a good answer from Apple Developer Relations. I'll quote the important bits:
NSKnownKeysDictionary1 is a Core Data voodoo that I do not understand. ... Clearly something is going wrong with its serialisation and deserialisation. Do you have Core Data up and running on both ends of the wormhole? Regardless, it might make more sense to do a deep copy of your bookmarks array (and anything else you get back from Core Data) so that you’re sending standard dictionaries across the ‘wire’ rather than Core Data stuff.
So my solution is either to add the Core Data framework to the extension or to do the deep copy. (I've temporarily done the former. The proper solution is probably the latter.)
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