My app is crashing with EXC_BAD_INSTRUCTION(code=EXC_i386_INVOP, subcode=0x0)
. The console logs (lldb)
. I'm trying to use NSUserDefaults
with NSKeyedArchiver
and NSKeyedUnarchiver
. The class I'm trying to serialise is a subclass of NSManagedObject
, so I can't serialise it directly (actually I can, but I can't deserialise it because it needs an NSManagedObjectContext
). But actually, if there's a way to serialise the class directly, please say so =)
To solve this problem, I create a NSDictionary with the same properties as the object and then serialise that. Here's how:
var userDefaults: NSUserDefaults = NSUserDefaults.standardUserDefaults();
var data: NSData? = userDefaults.dataForKey(DefaultSessionProfileKey);
// Only saves if necessary
if data == nil {
var dict: NSDictionary = [
"firstName": profile.firstName,
"lastName": profile.lastName,
"nameFormat": profile.nameFormat,
"gender": profile.gender,
"birthday": profile.birthday,
"picture": profile.picture,
"uid": profile.uid
];
// Save the profile to user defaults
data = NSKeyedArchiver.archivedDataWithRootObject(dict);
userDefaults.setObject(data, forKey: DefaultSessionProfileKey);
}
Then to do the opposite. This code crashes on the second line, when retrieving the data from the standard user defaults:
var userDefaults: NSUserDefaults = NSUserDefaults.standardUserDefaults();
var data: NSData? = userDefaults.dataForKey(DefaultSessionProfileKey);
var profile: Profile?;
if data != nil {
// Unserialize the profile data. We must serialize/deserialize an NSDictionary instead of directly using a Profile instance because Profile is NSMutableObject, which means that it cannot exist without an NSManagedObjectContext. We don't have one for the serialization/deserialization process, so we generate this dictionary first
var dict = NSKeyedUnarchiver.unarchiveObjectWithData(data) as NSDictionary;
if dict != nil {
// Create the profile instance
var appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate;
var entity: NSEntityDescription = NSEntityDescription.entityForName("Profile", inManagedObjectContext: appDelegate.managedObjectContext);
var profile: Profile = Profile(entity: entity, insertIntoManagedObjectContext: appDelegate.managedObjectContext);
profile.firstName = dict.objectForKey("first_name") as String;
profile.lastName = dict.objectForKey("last_name") as String;
profile.nameFormat = dict.objectForKey("name_format") as String;
profile.gender = dict.objectForKey("gender") as String;
profile.birthday = dict.objectForKey("birthday") as NSDate;
profile.picture = dict.objectForKey("picture") as String;
profile.uid = dict.objectForKey("uid") as String;
}
else {
// A profile exists in user defaults, but it's not a valid profile, so we take the chance to clean up
userDefaults.removeObjectForKey(DefaultSessionProfileKey);
}
}