Application crash while saving user object in NSUserDefaults

I have a custom class called User witch that conforms to the NSCoding protocol. But when I try to save it in NSUserDefaults, I get this error:

 Property list invalid for format: 200 (property lists cannot contain objects of type 'CFType') 

And this warning:

 NSForwarding: warning: object 0x7f816a681110 of class 'Shikimori.User' does not implement methodSignatureForSelector: -- trouble ahead Unrecognized selector -[Shikimori.User _copyDescription] 

User class:

 class User: NSCoding { private enum CoderKeys: String { case ID = "user.id" case Username = "user.username" case Email = "user.email" case Avatar = "user.avatar" } let id: Int let username: String let email: String let avatar: String init(id: Int, username: String, email: String, avatar: String) { self.id = id self.username = username self.email = email self.avatar = avatar } required init(coder aDecoder: NSCoder) { id = aDecoder.decodeIntegerForKey(CoderKeys.ID.rawValue) username = aDecoder.decodeObjectForKey(CoderKeys.Username.rawValue) as String email = aDecoder.decodeObjectForKey(CoderKeys.Email.rawValue) as String avatar = aDecoder.decodeObjectForKey(CoderKeys.Avatar.rawValue) as String } func encodeWithCoder(aCoder: NSCoder) { aCoder.encodeInteger(id, forKey: CoderKeys.ID.rawValue) aCoder.encodeObject(username as NSString, forKey: CoderKeys.Username.rawValue) aCoder.encodeObject(email as NSString, forKey: CoderKeys.Email.rawValue) aCoder.encodeObject(avatar as NSString, forKey: CoderKeys.Avatar.rawValue) } } 

Update Saving Code:

 let userKeyForDefaults = "apimanager.user" let defaults = NSUserDefaults.standardUserDefaults() defaults.setObject(user, forKey: self.userKeyForDefaults) 
+5
source share
1 answer

NSUserDefaults does not support all objects, such as NSString , NSDictionary and most importantly, NSData . It uses the NSCoding protocol. This allows us to convert custom objects into chunks of NSData . To do this, use the NSKeyedArchiver class to turn a custom object corresponding to NSCoding into an equivalent NSData

 let obj = User() let data = NSKeyedArchiver. archivedDataWithRootObject(obj) /// Now you can store data 

Documents can be found here and the method you are looking for is

 class func archivedDataWithRootObject(_ rootObject: AnyObject) -> NSData 

To retrieve information from NSUserDefaults , use the "reverse" class, NSKeyedUnarchiver . His suitable method is as follows

 class func unarchiveObjectWithData(_ data: NSData) -> AnyObject? 

Here is an example.

 let data = NSUserDefaults.standardUserDefaults().objectForKey("somekey") let obj = NSKeyedUnarchiver. unarchiveObjectWithData(data) as User? 

Note. I may have mixed up some additional options, but you get a jist. The documentation for NSKeyedUnarchiver can be found here .

Edit: Fixing a problem with OP was as simple as using NSKeyedArchiver and a subclass of NSObject .

+4
source

Source: https://habr.com/ru/post/1211223/


All Articles