iOS data Persistence ii-archive and design a data model base class that can be stored

Source: Internet
Author: User
<span id="Label3"></p><span id="OSC_h2_1"><span id="OSC_h2_1"></span></span>iOS data Persistence ii-archive and design a data model base class that can be stored<span id="OSC_h3_2"><span id="OSC_h3_2"></span></span>first, Introduction<br><p><p><span style="font-size: 16px;">in the previous blog, we introduced the method of data persistence using plist Files. It's easy to use, but with the development in-depth, you'll find that this approach still has a lot of limitations. imagine, If we can return the User's login information model, The role of the game character information model for direct persistent access, it is not very cool, fortunately, we can be archived to design a data model Such. </span><br></p></p><span id="OSC_h3_3"><span id="OSC_h3_3"></span></span><span style="font-size: 16px;"><span style="font-size: 16px;"><span style="font-size: 18px;">second, The first to master the archive it</span></span></span><p><p><span style="font-size: 18px;"><span style="font-size: 16px;">Archiving is also a way for iOS to store data for developers, and virtually all data types can be accessed through archiving. Its storage and reading process, mainly encapsulated in two classes: nskeyedarchiver and Nskeyedunarchiver.</span><br></span></p></p><span id="OSC_h4_4"><span id="OSC_h4_4"></span></span><span style="font-size: 18px;"><span style="font-size: 18px;"> <span style="font-size: 16px;">1, The principle of archiving<br></span></span></span><p><p><span style="font-size: 18px;"><span style="font-size: 16px;">Archiving is the serialization of one or more data types, the process of archiving is to deserialize the serialized data decoding, It is important to note that the core of the archive is not the persistence of data processing, but the data serialization processing, persistent processing is still through file access to Achieve. therefore, the archived data types must abide by an identical protocol, in order to be under the constraints of this Protocol to the correct archiving and archiving, this protocol is the Nscoding protocol, we can first look at the contents of Nscoding:<br></span></span></p></p><pre class="brush:cpp;toolbar: true; auto-links: false;"><pre class="brush:cpp;toolbar: true; auto-links: false;">@protocol nscoding-(void) encodewithcoder: (nscoder *) acoder;-(id) initwithcoder: (nscoder *) adecoder; @end</pre></pre><p><p></p></p><p><p><span style="font-size: 16px;"></span><span style="font-size: 16px;">This protocol is very simple, an init archiving method, a encode method of archiving, Nscoder is the archive object. In principle, regardless of the data type of the object, the system or our custom, you can implement the method in this protocol to support the archiving Operation.</span><br></p></p><span id="OSC_h4_5"><span id="OSC_h4_5"></span></span><span style="font-size: 16px;"><span style="font-size: 16px;">2. Application of several archives and solutions<br></span></span><span id="OSC_h5_6"><span id="OSC_h5_6"></span></span>(1) the Rootkey is archived by the class method<span style="font-size: 16px;"><span style="font-size: 16px;"><br></span></span><p><p> <span style="font-size:16px;">         This way, I personally understand that Very similar to standarduserdefaults in nsuserdefaults, but the latter is a default plist file that the system creates for us, and Rootkey is a default archive key value that the system creates for Us. It's more complicated than that, for example, it's very clear: </span> </p></p><pre class="brush:cpp;toolbar: true; auto-links: false;">NSString *homedictionary = nshomedirectory ();//get root directory nsstring *homepath = [homedictionary Stringbyappendingpathcompone nt:@ "atany.archiver"];//add stored file Name//mode one: archive data through data, write to file NSData *data= [nskeyedarchiver archiveddatawithrootobjec    t:@ "123"];    [data Writetofile:homepath atomically:yes];    Mode Two: write directly to the file [nskeyedarchiver archiverootobject:@ "456" tofile:homepath]; The effect of mode one and mode two is exactly the same as the time when the archive is Different//mode one of the solution archive: first to obtain data, the data in the solution archive NSLog (@ "%@", [nskeyedunarchiver unarchiveobjectwith    data:data]); The solution of mode two archives: the archive NSLog in the direct solution file (@ "%@", [nskeyedunarchiver unarchiveobjectwithfile:homepath]);</pre><p><p></p></p><p><p><span style="font-size: 16px;">The above example is an archive of a string type, an archive of a single data object, of course, where objects are supported in arrays, dictionaries, and so on, but all of the objects in the collection must also support archival operations.</span><br></p></p><span id="OSC_h5_7"><span id="OSC_h5_7"></span></span>(2) Archive multiple objects by constructing a new Archiver object<br><p><p><span style="font-size: 16px;">In addition to the class method above, we can construct an archive object ourselves to archive many different objects:</span><br></p></p><pre class="brush:cpp;toolbar: true; auto-links: false;">    nsstring *homedictionary = nshomedirectory ();//get root directory      nsstring *homepath  = [homedictionary stringbyappendingpathcomponent:@ " Atany.archiver "];//add stored file name     //here Create a mutable data object as an archive container      Nsmutabledata * data = [[nsmutabledata alloc]init];    //creating an Archive object , write data after archiving     NSKeyedArchiver * archiver = [[NSKeyedArchiver  Alloc]initforwritingwithmutabledata:data];    //archive serialization of the following string and int values      [archiver encodeobject:@ "jaki"  forkey:@ "name"];    [archiver  encodeint:24 forkey:@ "age"];    //write data    [archiver  finishencoding];    //writing Files     [data writeToFile:homePath  Atomically:yes];      &nBsp; //create a deserialized object to be archived     nskeyedunarchiver * unarchiver = [[ Nskeyedunarchiver alloc]initforreadingwithdata:data];    //for deserialization      nsstring * name = [unarchiver decodeobjectforkey:@ "name"];     int age = [unarchiver decodeintforkey:@ "age"];    //print Info      nslog (@ "\nname:%@\nage:%d", name,age);</pre><p><p></p></p><p><p><span style="font-size: 16px;">The results are as follows:</span><br></p></p><p><p><span style="font-size: 16px;"></span></p></p><span id="OSC_h5_8"><span id="OSC_h5_8"></span></span><span style="font-size: 16px;"><span style="font-size: 16px;"></span></span>(3) Archiving of Custom objects<br><p><p><span style="font-size: 16px;">As mentioned in the above introduction, in principle, any class that adheres to the Nscoding protocol can be archived, so what do we do with our custom objects?</span><br></p></p><p><p><span style="font-size: 16px;">first, we create a new class:</span></p></p><p><p><span style="font-size: 16px;">In the example above, we write a class like this:</span></p></p><pre class="brush:cpp;toolbar: true; auto-links: false;"><pre class="brush:cpp;toolbar: true; auto-links: false;">@interface myobject:nsobject@property (nonatomic,strong) NSString * name; @property (nonatomic,assign) int age; @end</pre></pre><p><p></p></p><p><p><span style="font-size: 16px;">To archive it:</span><br></p></p><pre class="brush:cpp;toolbar: true; auto-links: false;"><pre class="brush:cpp;toolbar: true; auto-links: false;">Archive MyObject * obj = [[MyObject alloc]init];    Obj.name = @ "jaki";    Obj.age = 24;    NSData * data = [nskeyedarchiver archiveddatawithrootobject:obj];    File MyObject * obj2 = [nskeyedunarchiver unarchiveobjectwithdata:data]; NSLog (@ "\nname:%@\nage:%d", obj2.name,obj2.age);</pre></pre><p><p></p></p><p><p><span style="font-size: 16px;">Run directly, The program will crash and print as Follows:</span><br></p></p><p><p><span style="font-size: 16px;"></span></p></p><p><p><span style="font-size: 16px;">As can be seen, we have said before, we must abide by the object of the archive protocol, can be archived, we implemented the following two methods in the MyObject class:</span></p></p><pre class="brush:cpp;toolbar: true; auto-links: false;"><pre class="brush:cpp;toolbar: true; auto-links: false;">Solution Method-(instancetype) initwithcoder: (nscoder *) coder{if (self=[super init]) {_name = [coder Decodeobjectforkey        : @ "name"];    _age = [coder decodeintforkey:@ "age"]; } return self;}    Archive Method-(void) encodewithcoder: (nscoder *) coder{[coder encodeobject:_name forkey:@ "name"]; [coder encodeint:_age forkey:@ "age"];}</pre></pre><p><p></p></p><p><p><span style="font-size: 16px;">Add the above two methods, our custom object can be freely archived access, and can write to local, very cool bar.</span><br></p></p><span id="OSC_h3_9"><span id="OSC_h3_9"></span></span><span style="font-size: 16px;"><span style="font-size: 16px;"><span style="font-size: 18px;">third, The design can be archived access to the data model base class</span></span></span><span id="OSC_h4_10"><span id="OSC_h4_10"></span></span><span style="font-size: 18px;"><span style="font-size: 18px;"><span style="font-size: 16px;">1. Motive and original intention</span><br></span></span><p><p><span style="font-size: 18px;"><span style="font-size: 16px;">With an introduction to the archive, we can find a very promising application for archiving: you can freely save data objects that are derived from the Definition. The advantage of this feature is no doubt that, in addition to making our data easier to use, there is no need to parse the data many times, and the security is Better. But there is also a flaw that each class needs to implement the two methods in the nscoding is very cumbersome, and the more complex the class, the more cumbersome the step, if in the subsequent modification and optimization of the class changes, the corresponding method will be changed, which would add a lot of work and the risk of embedding potential bugs.<br></span></span></p></p><p><p><span style="font-size: 18px;"><span style="font-size: 16px;">So we're going to think, can we design a model base class that inherits the model that needs to be stored, so that our model doesn't need to implement the Nscoding method while supporting archiving, and we can do that with some little tricks of runtime and OC language Features.<br></span></span></p></p><span id="OSC_h4_11"><span id="OSC_h4_11"></span></span><span style="font-size: 18px;"><span style="font-size: 18px;"> <span style="font-size: 16px;">2. Design of base class model<br></span></span></span><p><p> <span style="font-size:18px;"><span style="font-size:16px;">          We create a new Basemodel class with the following core methods: </span> </span> </p></p><pre class="brush:cpp;toolbar: true; auto-links: false;">Methods for archiving and archiving-  (instancetype) initwithcoder: (nscoder *) coder{    self = [ super init];    if  (self)  {         Get all Properties         nsarray * porpertyarray = [self  getAllPropertys];        for  (nsstring * name  in porpertyarray)  {            // Remove the _            nsstring * key in front of the property name  = [name substringFromIndex:1];             //agreed Key-value pair  c+key            [self  setvalue:[coder decodeobjectforkey:[nsstring stringwithformat:@ "c%@",key]] forKey:key];         }    }    return self;} -  (void) encodewithcoder: (nscoder *) coder{        //get All Properties     NSArray * porpertyArray = [self getAllPropertys];     for  (nsstring * name in porpertyarray)  {         //remove the _        nsstring * key in front of the property name  = [name substringfromindex:1];        //agreed Key-value pair  c +key        [coder encodeobject:[self valueforkey:key]  forkey:[nsstring stringwithformat:@ "c%@", Key]];    }}//get all the model properties-(NSArray *) getallpropertys{    nsmutablearray * array = [[nsmutablearray  alloc]init];      &Nbsp; unsigned int * count = malloc (sizeof (unsigned int));     //call Runtime Method     //ivar: method returns the object content object, here will return a pointer of type Ivar     / The/class_copyivarlist method can capture all variables of a class, and the number of variables exists in a unsigned int pointer     ivar * mem  = class_copyivarlist ([self class], count);     //traverse      for  (int i=0; i< *count ; i++)  {         //traversal by moving the pointer         Ivar var =  *  (mem+i);         //gets The name of the variable          const char * name = ivar_getname (var);         nsstring * str = [nsstring stringwithcstring:name encoding: Nsutf8stringencoding];        [array addobject:str];    }     Free memory     free (count);     //note handling Wild hands     count=nil;     return array;}</pre><p><p></p></p><p><p><span style="font-size: 16px;"></span><span style="font-size: 16px;">Through such a runtime mechanism, we can easily be the new model inherited from the base class, no other processing directly supporting the archive, modification and optimization are Unaffected.</span><br></p></p><span id="OSC_h3_12"><span id="OSC_h3_12"></span></span><span style="font-size: 16px;"><span style="font-size: 16px;"> <span style="font-size: 18px;">iv. Sharing for like-minded friends</span><br></span></span><p><p><span style="font-size: 18px;"><span style="font-size: 16px;">This model is integrated in one of my open source development frameworks, and of course, it's also integrated and many many such handy features for developers to use if you're interested in https://github.com/ZYHshao/ Yhbasefoundationtest</span> <span style="font-size: 16px;">See Above. If you find some bugs or places you can add or optimize, be sure to let me know and thank you very much. qq:316045346</span><br></span></p></p><p><p>iOS data Persistence ii-archive and design a data model base class that can be stored</p></p></span>
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.