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.
See this answer if you want to change the display name of an OS X app.
Related Topics
iOS 13.2 Message: Nehelper Sent Invalid Result Code [1] for Wi-Fi Information Request
Uitableview Scroll Erases Data in Text Field Inside UItableviewcell
Draw Polyline Using Google Maps in Custom View with Swift 3
Conversion from String to Date in Swift Returns Nil
Realm Crashes with Rlmexception: Object Has Been Deleted or Invalidated
Exceeding Max Text("") Concatenation Length - Swiftui -
Stick UItableview Header View to Top When Creating Header in Storyboard
Will Download Resume After Closing My App in Background Mode
Can't Update Google Admob in iOS Project
How to Draw a Uilabel with a Different Blend Mode in Draw(_ Rect: Cgrect) in Swift
iOS UIlabel Autoshrink So Word Doesn't Truncate to Two Lines
Getting Email Address from Linkedin API
Swift - Add Same Navigation Bar Items to Every Page
Why [Uiscreen Mainscreen].Bounds] Is Not Returning Full Screen Size
Gcm Support for iOS Application When Application in Background or Killed
Start Position of Table View Is Wrong in Simulator, and Is Not The Same in Storyboard