iOS develops simple and efficient data storage

Source: Internet
Author: User
<span id="Label3"></p><p><p></p></p><p><p></p></p><p><p></p></p><p><p>In the process of iOS development, no matter what the application, you will encounter the problem of data preservation, what method do you use to persist data? This is an issue that will be mentioned in almost every communication or discussion about iOS technology, and everyone's enthusiasm for the issue continues to soar. This paper mainly from the concept of "data storage" the problem of analysis, and combined with their respective characteristics and the application of the scene for a comprehensive analysis.</p></p><p><p></p></p><p><p><strong>Nsuserdefaults</strong></p></p><p><p></p></p><p><p>Nsuserdefaults is designed to store configuration information for devices and applications, and it returns the default, and most commonly used, instance objects through a factory method. This object stores the configuration information of the user in the system, which can be modified by the instance object, or the new configuration items can be created according to their own requirements.</p></p><p><p></p></p><p><p>The types of data that Nsuserdefaults can store include: nsdata, nsstring, nsnumber, nsdate, nsarray, nsdictionary. If you want to store other types, you need to convert to the previous type to use Nsuserdefaults Storage. The specific implementation is:</p></p><p><p></p></p><p><p>Save Data:</p></p><p><p></p></p> <blockquote> <blockquote> <p>Nsuserdefaults *defaults =[nsuserdefaults standarduserdefaults];</p> <p>NSString *name [email protected] "default string";</p> <p>[defaults setobject:firstname forkey:@ "name"];</p> <p>Get UIImage instances</p> </blockquote> </blockquote><p><p></p></p> <blockquote> <blockquote> <p>UIImage *image=[[uiimage alloc]initwithcontentsoffile:@ "photo.jpg"];</p> <p> </p> <p>NSData *imagedata = UIImageJPEGRepresentation (image),//uiimage object converted to NSData</p> <p> </p> <p>[defaults synchronize]; Persisting data to the Standarduserdefaults database using the Synchronize method</p> </blockquote> </blockquote><p><p></p></p><p><p>Read Data:</p></p><p><p></p></p> <blockquote> <blockquote> <p>Nsuserdefaults *defaults =[nsuserdefaults standarduserdefaults];</p> <p>NSString *name = [defaults objectforkey:@ "name"]; Remove name based on key value</p> <p>NSData *imagedata = [defaults dataforkey:@ "image"];</p> <p>UIImage *image = [UIImage imagewithdata:imagedata]; NSData Conversion to UIImage</p> </blockquote> </blockquote><p><p></p></p><p><p><strong>archive, Unpack</strong></p></p><p><p></p></p><p><p><strong>nskeyedarchiver:</strong> in the form of an archive, the data object needs to adhere to the nscoding protocol, and the class corresponding to the object must provide Encodewithcoder: and Initwithcoder: methods. The previous method tells the system how to encode the object, and the latter method tells the system how to decode the Object. For example, Save the possession object Archive.</p></p><p><p></p></p><p><p>Define Possession:</p></p><p><p></p></p> <blockquote> <blockquote> <p>@interface Possession:nsobject<nscoding>{//compliance with nscoding protocol</p> <p>NSString *name;//pending Archive Type</p> <p>}</p> <p>@implementation Possession</p> <p>-(void) encodewithcoder: (nscoder *) acoder{</p> <p>[acoder encodeobject:name forkey:@ "name"];</p> <p>}</p> <p>-(void) initwithcoder: (nscoder *) adecoder{</p> <p>Name=[[adecoder decodeobjectforkey:@ "name"] retain];</p> <p>}</p> </blockquote> </blockquote><p><p></p></p><p><p>Archive Operations:</p></p><p><p></p></p><p><p>If you save the possession object Allpossession archive, you only need to nscoder the method Archiverootobject:tofile of the subclass Nskeyedarchiver: Yes.</p></p><p><p></p></p> <blockquote> <blockquote> <p>NSString *path = [self possessionarchivepath];</p> <p>[nskeyedarchiver archiverootobject:allpossessions tofile:path]</p> </blockquote> </blockquote><p><p></p></p><p><p>Decompression Operation:</p></p><p><p></p></p><p><p></p></p> <blockquote> <blockquote> <p>Also call the method of Nscoder subclass Nskeyedarchiver Unarchiverootobject:tofile: You can</p> <p>Allpossessions = [[nskeyedunarchiver unarchiveobjectwithfile:path] retain];</p> </blockquote> </blockquote><p><p></p></p><p><p>Cons: Archive the form to save data, only one-time archive save and one-time Decompression. So only a small amount of data, and the data operation is clumsy, that is, if you want to change a small part of the data, still need to extract the entire data or archive the entire Data.</p></p><p><p></p></p><p><p><strong>Sqlite</strong></p></p><p><p></p></p><p><p>Using SQLite storage to query more data is the most common way in our development, such as app interface data cache, offline cache and so On.</p></p><p><p></p></p><p><p>First step: you need to add SQLite related libraries and header files: under build phases of the project file, locate the link Binary Library (ies) and add Libsqlite3.0.dylib</p></p><p><p>(the difference between the Libsqlite3.dylib and the former is not known, the two should be similar); add a header file to the header file or source file in the project file #import "/usr/include/sqlite3.h"</p></p><p><p></p></p><p><p>Step two: start using sqlite:</p></p><p><p></p></p> <blockquote> <p><p>Nsarray *documentspaths=nssearchpathfordirectoriesindomains (nsdocumentdirectory, NSUserDomainMask, YES);</p></p> <p><p>NSString *databasefilepath=[[documentspaths objectatindex:0] stringbyappendingpathcomponent:@ "mydb"];</p></p> <p><p>The above two sentences are already more familiar with it!</p></p> <p><p>Open Database</p></p> <p><p>If (sqlite3_open ([databasefilepath utf8string], &database) ==sqlite_ok) {</p></p> <p><p>NSLog (@ "sqlite Dadabase is opened.");</p></p> <p><p>}</p></p> <p><p>else{return;} Turn on unsuccessful to return</p></p> <p><p>When the database is open, if the database does not have a table, then you start to build the table oh!</p></p> <p><p>Char *error;</p></p> <p><p>const char *createsql= "create table (id Integer primary key autoincrement, name text)";</p></p> <p><p>If (sqlite3_exec (database, createsql, null, null, &error) ==sqlite_ok) {</p></p> <p><p>NSLog (@ "create table is ok.");</p></p> <p><p>}</p></p> <p><p>Else</p></p> <p><p>{</p></p> <p><p>NSLog (@ "error:%s", error);</p></p> <p><p>Sqlite3_free (error);//empty the error string each time it is used, provided to the next use</p></p> <p><p>}</p></p> </blockquote><p><p></p></p><p><p>After the build table is complete, insert the Record:</p></p><p><p></p></p> <blockquote> <blockquote> <p>const char *insertsql= "insert into a person (name) values (' GG ')";</p> <p>If (sqlite3_exec (database, insertsql, null, null, &error) ==sqlite_ok) {</p> <p>NSLog (@ "insert operation is ok.");</p> <p>}</p> <p> </p> <p>Else</p> <p>{</p> <p>NSLog (@ "error:%s", error);</p> <p>Sqlite3_free (error);//empty the error string each time it is used, provided to the next use</p> <p>}</p> </blockquote> </blockquote><p><p></p></p><p><p>next, Query the Record:</p></p><p><p></p></p> <blockquote> <blockquote> <p>const char *selectsql= "select id,name from a person";</p> <p>Sqlite3_stmt *statement;</p> <p>If (sqlite3_prepare_v2 (database,selectsql,-1, &statement, nil) ==sqlite_ok) {</p> <p>NSLog (@ "select operation is ok.");</p> <p>}</p> <p>Else</p> <p>{</p> <p>NSLog (@ "error:%s", error);</p> <p>Sqlite3_free (error);</p> <p>}</p> <p>While (sqlite3_step (statement) ==sqlite_row) {</p> <p>int _id=sqlite3_column_int (statement, 0);</p> <p>NSString *name= (char*) sqlite3_column_text (statement, 1);</p> <p>NSLog (@ "row>>id%i, name%s", _id,name);</p> <p>}</p> <p>Sqlite3_finalize (statement);</p> </blockquote> </blockquote><p><p></p></p><p><p>finally, Close the Database:</p></p><p><p></p></p> <blockquote> <blockquote> <p>Sqlite3_close (database);</p> </blockquote> </blockquote><p><p></p></p><p><p><strong>note:</strong> to write to a database, the string can be char, and the char type is removed from the database and garbled when the char type has a representation of the Chinese Characters. This is because the database uses ASCII encoding by Default. therefore, in order to correctly remove the Chinese from the database, we need to use NSString to receive the string extracted from the Database.</p></p><p><p></p></p><p><p><strong>CoreData</strong></p></p><p><p></p></p><p><p>Core data is more object-oriented than using the SQLite3 API directly, and the operation process is usually divided into the following steps:</p></p><p><p></p></p><p><p><strong>1. Create a Management context</strong></p></p><p><p></p></p><p><p>Creation management can be subdivided into: load model file, Specify Datastore path, create a corresponding data type, create a Management object below and specify Storage.</p></p><p><p></p></p><p><p>After these steps, you can get the management object context nsmanagedobjectcontext, in which all data operations are responsible for this Object. At the same time, if the context is created for the first time, Core data automatically creates a storage file (for example, using SQLite3 storage) and creates a corresponding table structure based on the model Object. The database and related mapping files that were generated for the first run:</p></p><p><p></p></p><p><p>To facilitate later use, the Nsmanagedobjectcontext object can be saved as a singleton or a static property, and the following is the main code for the created Management object Context:</p></p><p><p></p></p> <blockquote> <p><p>-(nsmanagedobjectcontext *) createdbcontext{</p></p> <p><p>Nsmanagedobjectcontext *context;</p></p> <p><p>Open the model file, and the parameter is nil to open all the model files in the package and merge them into one</p></p> <p><p>Nsmanagedobjectmodel *model=[nsmanagedobjectmodel mergedmodelfrombundles:nil];</p></p> <p><p>Creating a parser</p></p> <p><p>Nspersistentstorecoordinator *storecoordinator=[[nspersistentstorecoordinator Alloc]initWithManagedObjectModel: model];</p></p> <p><p>Create a database save path</p></p> <p><p>NSString *dir=[nssearchpathfordirectoriesindomains (nsdocumentdirectory, nsuserdomainmask, YES) firstObject];</p></p> <p><p>NSLog (@ "%@", dir);</p></p> <p><p>NSString *path=[dir stringbyappendingpathcomponent:@ "mydatabase.db"];</p></p> <p><p>Nsurl *url=[nsurl fileurlwithpath:path];</p></p> <p><p>Add SQLite persistent store to parser</p></p> <p><p>Nserror *error;</p></p> <p><p>[storecoordinator addpersistentstorewithtype:nssqlitestoretype configuration:nil URL:url options:nil error:& error];</p></p> <p><p>If (error) {</p></p> <p><p>NSLog (@ "database Open failed! error:%@ ", error.localizeddescription);</p></p> <p><p>}else{</p></p> <p><p>Context=[[nsmanagedobjectcontext alloc]init];</p></p> <p><p>context.persistentstorecoordinator=storecoordinator;</p></p> <p><p>NSLog (@ "database Open successfully! ");</p></p> <p><p>}</p></p> <p><p>Return context;</p></p> <p><p>}</p></p> </blockquote><p><p></p></p><p><p><strong>2. Querying data</strong></p></p><p><p><strong></strong></p></p><p><p>For a conditional query, it is implemented through a predicate in core Data. You first create a request, then set the request criteria, and finally call the context to execute the requested Method.</p></p><p><p></p></p> <blockquote> <blockquote> <p>-(void) adduserwithname: (nsstring *) name screenname: (nsstring *) screenname profileimageurl: (nsstring *) Profileimageurl mbtype: (nsstring *) mbtype city: (nsstring *) city{</p> <p>Add an Object</p> <p>User *us= [nsentitydescription insertnewobjectforentityforname:@ "user" inManagedObjectContext:self.context];</p> <p>us.name=name;</p> <p>us.screenname=screenname;</p> <p>us.profileimageurl=profileimageurl;</p> <p>us.mbtype=mbtype;</p> <p>us.city=city;</p> <p>Nserror *error;</p> <p>Save context</p> <p>If (![ Self.context Save:&error]) {</p> <p>NSLog (@ "error occurred during add, error message:%@! ", error.localizeddescription);</p> <p>}</p> <p>}</p> </blockquote> </blockquote><p><p></p></p><p><p>If there are multiple conditions, as long as a combination of predicates, then how to query the associated object conditions? Here are two scenarios to introduce:</p></p><p><p></p></p><p><p>A. Finding a single object with only one associated object, such as finding a Weibo user named "Binger" (a microblog can only belong to one user), through-</p></p><p><p></p></p> <blockquote> <blockquote> <p>(nsarray) getstatusesbyusername: (nsstring) name{</p> <p>Nsfetchrequest *request=[nsfetchrequest fetchrequestwithentityname:@ "Status"];</p> <p>Request.predicate=[nspredicate predicatewithformat:@ "user.name=%@", name];</p> <p>Nsarray *array=[self.context executefetchrequest:request error:nil];</p> <p>Return array; The SQL statement generated by}ata will find that the status table and the user table are actually associated with the query (join connection).</p> </blockquote> </blockquote><p><p></p></p><p><p>B. Find a situation where an object has multiple associated objects, such as a user who has "Watch" in the sending microblogging content and a user nickname "cortana" (one user has multiple tweets), the predicate can be used to</p></p><p><p></p></p> <blockquote> <blockquote> <p>-(nsarray) getusersbystatustext: (nsstring) text screenname: (nsstring *) screenname{</p> <p>Nsfetchrequest *request=[nsfetchrequest fetchrequestwithentityname:@ "Status"];</p> <p>Request.predicate=[nspredicate predicatewithformat:@ "text like ' Watch '", text];</p> <p>Nsarray *statuses=[self.context executefetchrequest:request error:nil];</p> </blockquote> </blockquote><p><p></p></p> <blockquote> <blockquote> <p>Nspredicate *userpredicate= [nspredicate predicatewithformat:@ "user.screenname=%@", screenName];</p> <p>Nsarray *users= [statuses filteredarrayusingpredicate:userpredicate];</p> <p>Return users;</p> </blockquote> </blockquote><p><p></p></p><p><p>If you simply look for a user with a "Watch" in your microblog, you can find the corresponding Weibo directly, and then get the user by using each of the Weibo's user attributes, without the use of additional predicate filters.</p></p><p><p></p></p><p><p><strong>3. Inserting data</strong></p></p><p><p></p></p><p><p>Inserting data requires calling the entity Description Object Nsentitydescription returns an entity object, sets the object properties, and finally saves the current Context. It is important to note that the Save method of the Management object context must be called at the end of the add, delete, and change operation, otherwise the operation will not Execute.</p></p><p><p></p></p> <blockquote> <blockquote> <p>-(void) adduserwithname: (nsstring *) name screenname: (nsstring *) screenname profileimageurl: (nsstring *) Profileimageurl mbtype: (nsstring *) mbtype city: (nsstring *) city{</p> <p>Add an Object</p> <p>User *us= [nsentitydescription insertnewobjectforentityforname:@ "user" inManagedObjectContext:self.context];</p> <p>us.name=name;</p> <p>us.screenname=screenname;</p> <p>us.profileimageurl=profileimageurl;</p> <p>us.mbtype=mbtype;</p> <p>us.city=city;</p> <p>Nserror *error;</p> <p>Save context</p> <p>If (![ Self.context Save:&error]) {</p> <p>NSLog (@ "error occurred during add, error message:%@! ", error.localizeddescription);</p> <p>}</p> <p>}</p> </blockquote> </blockquote><p><p></p></p><p><p><strong>4. Delete Data</strong></p></p><p><p></p></p><p><p>Deleting data can directly invoke the DeleteObject method that manages the object context, removing the Save Context. Note that you must first query the corresponding object before deleting the Data.</p></p><p><p></p></p> <blockquote> <blockquote> <p>-(void) removeuser: (User *) user{</p> <p>[self.context deleteobject:user];</p> <p>Nserror *error;</p> <p>If (![ Self.context Save:&error]) {</p> <p>NSLog (@ "error occurred during deletion, error message:%@!", error.localizeddescription);</p> <p>}</p> <p>}</p> </blockquote> </blockquote><p><p></p></p><p><p><strong>5. Modify the data</strong></p></p><p><p></p></p><p><p>Modifying the data first also takes out the corresponding entity object, and then saves the context by modifying the Object's Properties.</p></p><p><p></p></p> <blockquote> <blockquote> <p>-(void) modifyuserwithname: (nsstring *) name screenname: (nsstring *) screenname profileimageurl: (nsstring *) Profileimageurl mbtype: (nsstring *) mbtype city: (nsstring *) city{</p> <p>User *us=[self getuserbyname:name];</p> <p>us.screenname=screenname;</p> <p>us.profileimageurl=profileimageurl;</p> <p>us.mbtype=mbtype;</p> <p>us.city=city;</p> <p>Nserror *error;</p> <p>If (![ Self.context Save:&error]) {</p> <p>NSLog (@ "error occurred during modification, error message:%@", error.localizeddescription);</p> <p>}</p> <p>}</p> </blockquote> </blockquote><p><p></p></p><p><p><strong>Debugging</strong></p></p><p><p></p></p><p><p>While core Data (if using SQLite database) operations eventually translates to SQL operations, debugging does not make it easy to manipulate sql. Especially for beginners, the problem of query error often occurs, if you can see the resulting SQL statement is naturally useful for debugging. In fact, in Xcode support core Data debugging, the Operation: product-scheme-edit Add two parameters in Scheme-run-arguments (note that the parameter order cannot be wrong):-com.apple.coredata.sqldebug, 1. then, when you run the program, the SQL statement is printed in the output panel if you manipulate the Database.</p></p><p><p></p></p><p><p>iOS develops simple and efficient data storage</p></p></span>

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.