Swift: Save complex objects with Userdefaults

Source: Internet
Author: User

Wood has seen this detail, with Userdefaults is not able to save a more complex object. You may have seen a method of Userdefaults, which has been setObject: forKey: stored in this way, and NSDictionary NSArray has been stored in a string.

Accidentally saved an inherited JSONModel entity class directly, and then it was tragic. Later, I looked up the following Apple documents:

The value parameter can be only property list objects: NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. For NSArray and NSDictionary objects, their contents must be property list objects.

In simple terms setObject:forKey: , the method can be stored NSData , NSString what the object, even if NSDictionary and NSArray inside the element must also be the property list objects. Specifically what is the property list object look here. About JSONModel can see here, also good.

Now that Apple's API has been limited to this point, think of nothing else to play out. Yes, you can save the file. But it's still about using Userdefaults.

The core idea of solving this problem is to convert an object to NSData , or to be serialized NSData . Serialization is not necessarily accurate, but there is such a process, the specific later to elaborate. When an object can be converted into NSData a method that is also applicable NSUserDefaults setObject: forKey: . This is the usage:

Suppose there is a user entity class Usermodel {    var userid:string = ""    var accesstoken:string = ""}//then let Usermodel = Usermodel ()//formally start let Userdefaults = Nsuserdefaults.standarduserdefaults () Get encodedobject = Nskeyedarchiver.archiveddatawithrootobject (object) userdefaults.setobject (Encodedobject, ForKey: "UserInfoKey") Userdefaults.synchronize ()//finally don't forget this.

The general meaning is reflected in all the above code. But if you run the above code, it's definitely going to go wrong.

to uncaught exception ‘NSInvalidArgumentException‘, reason: ‘Attempt to insert non-property list object UserModel for key UserInfoKey‘

Because it is not a property list Object setObject:forKey , the app directly crash when executing the method.

This problem seems to be on the property list object. But back to what is said, our idea is to convert the object of this custom entity class into a NSData . This time will be used NSKeyedArchiver and NSKeyedUnarchiver , this also indirectly used the NSCoding interface. Because if an entity class is not implemented NSCoding then there will be errors on NSKeyedArchiver and NSKeyedUnarchiver off.

Make a small improvement to the above code:

Class Weibousermodel:nsobject, nscoding {//1 struct PropertyKey {static let Useridkey = "UserId" Stati C Let Accesstokenkey = ' accesstoken ' static let Expirationdatekey = ' expirationdate ' static Let Refreshtoken    Key = "Refreshtoken"} var userid:string?    var accesstoken:string?    var expirationdate:nsdate?    var refreshtoken:string? Func Encodewithcoder (acoder:nscoder) {//2 acoder.encodeobject (userId, ForKey:PropertyKey.userIdKey) acod Er.encodeobject (Accesstoken, ForKey:PropertyKey.accessTokenKey) acoder.encodeobject (ExpirationDate, Forkey:proper Tykey.expirationdatekey) Acoder.encodeobject (Refreshtoken, ForKey:PropertyKey.refreshTokenKey)} required in It? (Coder Adecoder:nscoder) {//3 UserId = Adecoder.decodeobjectforkey (Propertykey.useridkey) as? String Accesstoken = Adecoder.decodeobjectforkey (Propertykey.accesstokenkey) as? String expirationdate = adecoder.decodeobjectforKey (Propertykey.expirationdatekey) as? NSDate Refreshtoken = Adecoder.decodeobjectforkey (Propertykey.refreshtokenkey) as? String}}

Such a modification would allow them to run. The following is explained in turn:
1. Implementation NSObject and NSCoding . NSObjectyou can do it without adding @objc some methods to modify it. The NSCoding interface provides a way to encode and decode objects as they are serialized and deserialized.

    UserModelThe class name is modified to WeiboUserModel . This part of the code is part of the entire project and will be filled in later.

2. Use the method encoding when serializing an object. func encodeWithCoder(aCoder: NSCoder)
3. Use the decoding method when deserializing. init?(coder aDecoder: NSCoder)

Under the condition that the general logic does not modify, we look at the complete code that can save the entity class object.

Then let Usermodel = Weibousermodel ()//formal start to get userdefaults = Nsuserdefaults.standarduserdefaults () to Encodedobject = Nskeyedarchiver.archiveddatawithrootobject (object) userdefaults.setobject (Encodedobject, ForKey: "UserInfoKey") Userdefaults.synchronize ()//finally don't forget this.

So you can run it. But we can't stop here. Because if there are too many places in the project that need to be saved, the calls are filled with (most likely, copy-and-paste) NSUserDefaults instances. This kind of code is too rigid. And it's easy to forget the last userDefaults.synchronize () call. This can cause problems with the storage of objects.

So we're going to do some encapsulation of this part of the code:

Extension Nsuserdefaults {//1    func savecustomobject (customobject object:nscoding, key:string) {//2 let        encode Dobject = Nskeyedarchiver.archiveddatawithrootobject (object)        self.setobject (Encodedobject, Forkey:key)        Self.synchronize ()    }    func getcustomobject (Forkey key:string), Anyobject? {//3 let        decodedobject = Self.objectforkey (key) as? NSData        if let decoded = decodedobject {Let            object = Nskeyedunarchiver.unarchiveobjectwithdata (decoded)            Return Object        }        return nil    }}

We put the methods of access in NSUserDefaults the extension. This way the user can use the same as the NSUserDefaults method of using itself. And the synchronize() method is encapsulated inside, no longer have to worry about forgetting that the D object has not been saved. Take a look at a small detail of the call.

Userdefaults.savecustomobject (Customobject:usermodel, Key: "Userinfokey")//Save Userdefaults.getcustomobject (" Userinfokey ") as? Weibousermodel//Fetch

Okay, here it is.

To be Continued

Swift: Save complex objects with Userdefaults

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.