Reputation: 893
I'm introducing Realm into my swift project. I have a User class that I was saving an instance of into NSUserDefaults to keep track of the 1 logged in user.
After making User a subclass of Object, I get the following error when trying to unarchive (archiving seems to work OK):
Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: '*** -[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (RLMStandalone_User) for key (root); the class may be defined in source code or a library that is not linked'
I have Realm installed as a Cocoapod, this are the relevant methods in the User clas
static var currentUser: User? {
get {
if let data = NSUserDefaults.standardUserDefaults().objectForKey(UserDefaultKeys.kUserData) as? NSData,
let user = NSKeyedUnarchiver.unarchiveObjectWithData(data) as? User {
return user
} else {
return nil
}
}
set {
if let user = newValue {
let data = NSKeyedArchiver.archivedDataWithRootObject(user)
NSUserDefaults.standardUserDefaults().setObject(data, forKey: UserDefaultKeys.kUserData)
NSUserDefaults.standardUserDefaults().synchronize()
} else {
NSUserDefaults.standardUserDefaults().removeObjectForKey(UserDefaultKeys.kUserData)
NSUserDefaults.standardUserDefaults().synchronize()
}
}
}
// MARK: NSCoding
convenience init?(coder decoder: NSCoder) {
self.init()
guard let firstName = decoder.decodeObjectForKey("firstName") as? String,
let lastName = decoder.decodeObjectForKey("lastName") as? String,
let email = decoder.decodeObjectForKey("email") as? String,
let icloud = decoder.decodeObjectForKey("icloudUserID") as? String,
let userType = decoder.decodeObjectForKey("userType") as? String
else {
return nil
}
self.firstName = firstName
self.lastName = lastName
self.email = email
self.profilePic = decoder.decodeObjectForKey("profilePic") as? String
self.icloudUserID = icloud
self.userType = userType
self.coverPhoto = decoder.decodeObjectForKey("coverPhoto") as? String
self.facebookID = decoder.decodeObjectForKey("facebookID") as? String
self.placeID = decoder.decodeObjectForKey("placeID") as? String
}
func encodeWithCoder(coder: NSCoder) {
coder.encodeObject(self.firstName, forKey: "firstName")
coder.encodeObject(self.lastName, forKey: "lastName")
coder.encodeObject(self.icloudUserID, forKey: "icloudUserID")
coder.encodeObject(self.userType, forKey: "userType")
coder.encodeObject(email, forKey: "email")
if let coverPhotoUrl = self.coverPhotoUrl {
coder.encodeObject(coverPhotoUrl, forKey: "coverPhoto")
}
if let profilePicUrl = self.profilePicUrl {
coder.encodeObject(profilePicUrl, forKey: "profilePic")
}
if let fbID = self.facebookID {
coder.encodeObject(fbID, forKey: "facebookID")
}
if let placeID = self.placeID {
coder.encodeObject(placeID, forKey: "placeID")
}
}
Upvotes: 1
Views: 734
Reputation: 15991
It's not possible to store a Realm Object
in NSUserDefaults
as (As you saw in that error message) they cannot be serialized or deserialized by the NSCoding
protocol.
Instead, it might be better to add a primary key property to your User
object (So you can use it to query that exact object from Realm), and store the primary key itself in NSUserDefaults
instead.
Or better yet, instead of relying on NSUSerDefaults
, it might be better to simply have a boolean property, isCurrent
in your model, and using that to work out which user is the current one.
Upvotes: 3
Reputation: 674
You should keep your NSUserDefaults and your Realm data separate. They are two different methods of persistent data storage. If you've converted something to a Realm Object, you no longer need to (or should) try and put that into NSUserDefaults.
Upvotes: 1