Added a Custom Framework, Now Swift Can't Unarchive Data

Added a custom framework, now Swift can't unarchive data

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. The fix was to add this line before unarchiving:

NSKeyedUnarchiver.setClass(DemoNote.self, forClassName: "DemoNotesSwift.DemoNote")

In this case, DemoNote.self gets the current full class name, and DemoNotesSwift.DemoNote is what the class used to be called when it was part of the app.

This was only necessary because I had previously existing data that I wanted to keep.

How to archive and unarchive custom objects in Swift? Or how to save custom object to NSUserDefaults in Swift?

NSKeyedArchiver will only work with Objective-C classes, not pure Swift classes. You can bridge your class to Objective-C by marking it with the @objc attribute or by inheriting from an Objective-C class such as NSObject.

See Using Swift with Cocoa and Objective-C for more information.

Cannot decode object of class

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.

Error [general] *** -[NSKeyedUnarchiver validateAllowedClass:forKey:] allowed unarchiving ...

Thanks to @OI Sen it've had a closer look to the NSUnarchiver.
First of all NSKeyedUnarchiver should be allocated and initialized like this:

NSError* err;

NSKeyedUnarchiver* unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:someData error:&err];

In my specific case I use NSSecure coding. Therefore you have to specify classes on decoding objects. In my case it looked like this

NSDictionary* someDict = [unarchiver decodeObjectOfClass:[NSDictionary class] forKey:NSKeyedArchiveRootObjectKey];

But the NSDictionary contained additional strings. That was the cause of the log message. By adding NSString to the decoded class list the error is gone.

NSDictionary* someDict = [unarchiver decodeObjectOfClasses:[[NSSet alloc] initWithArray:@[[NSDictionary class],[NSString class]]] forKey:NSKeyedArchiveRootObjectKey];

NSKeyedUnarchiver error after renaming Xcode project

Don't change your project name. Just change the display name. It's the "Bundle display name" entry in your Info.plist. You'll probably need to add the entry.

adding Bundle display name to Info.plist

See this answer if you want to change the display name of an OS X app.



Related Topics



Leave a reply



Submit