In-depth understanding of iPhone data persistence

Source: Internet
Author: User

Data persistence on all mobile development platforms is a very important part: In j2s, It is RMS or stored in the application directory, in Symbian, it can be stored in the corresponding disk directory and in the database. In Symbian, due to permission authentication, most 3rd users can only access private directories of applications or shared directories of other systems. On the iPhone, Apple has made great strides and provided a variety of data persistence methods. I will explain them in detail one by one.

The data persistence method provided by the iPhone can be divided into three parts from the data storage method: attribute list, object archiving, Embedded Database (sqlite3), and other methods.

I, Attribute list nsuserdefaults

The use of the nsuserdefaults class is similar to that of the nskeyedarchiver class. However, according to the definition of nsuserdefaults, nsuserdefaults inherits from nsobject and nskeyedarchiver inherits from nscoder. This means that nskeyedarchiver is actually an archive persistence class. You can use the [encodeobject: (ID) objv forkey :( nsstring *) Key] method of the nscoder class to store data persistently.

 

-(Void) applicationdidfinishlaunching :( uiapplication *) Application {
Nsstring * strone = @ "persistent data1 ";
Nsstring * strtwo = @ "persistent data 2 ";
 
Nsmutablearray * persistentarray = [[nsmutablearray alloc] init];
[Persistentarray addobject: strone];
[Persistentarray addobject: strtwo];
 
// Archive
Nsuserdefaults * persistentdefaults = [nsuserdefaults standarduserdefaults];
[Persistentdefaults setobject: persistentarray forkey: @ "mydefault"];
Nsstring * descriptiondefault = [persistentdefaults description];
Nslog (@ "nsuserdefaults description is: % @", descriptiondefault );
 
// Unarchive
Nsarray * unpersistentarray =

[Persistentdefaults objectforkey: @ "mydefault"];

Nsstring * unstrone = [unpersistentarray objectatindex: 0];
Nsstring * unstrtwo = [unpersistentarray objectatindex: 1];
 
Nslog (@ "unstrone =%@, unstrtwo =%@", unstrone, unstrtwo );
 
// Override point for customization after application launch
[Window makekeyandvisible];
}


2. Object archiving nskeyedarchiver and nskeyedunarchiver

Like the Symbian 3rd, the iPhone generates a private directory for each application, which is located in

/Users/sundfsun2009/library/Application Support/iPhone simulator/user/applications, and a digital sequence string is generated as the directory name. When each application is started, this letter and digit string is different from the last time, and the last application directory information is converted. ds_store hides the file. The file structure of this directory is as follows:

The documents directory is usually used for persistent data storage. The documents directory can be obtained through nssearchpathfordirectoriesindomains (nsdocumentdirectory, nsuserdomainmask, yes). The Code is as follows:

-(Void) applicationdidfinishlaunching :( uiapplication *) Application {

Nsstring * strone = @ "persistent data1 ";
Nsstring * strtwo = @ "persistent data 2 ";
 
Nsarray * persistentarray = [nsarray arraywithobjects: strone, strtwo, nil];
Nsarray * patharray = nssearchpathfordirectoriesindomains (nsdocumentdirectory, nsalldomainsmask, yes );
 
Int pathlen = [patharray count];
 
Nslog (@ "path number is: % d", pathlen );
 
Nsstring * filepath;
 
For (INT I = 0; I <pathlen; I ++)
{
Filepath = [patharray objectatindex: I];
Nslog (@ "% d path is: % @", I, filepath );
}
 
Nsstring * myfilename = [filepath stringbyappendingpathcomponent: @ "myfile. rtf"];
 
Nslog (@ "myfile's path is: % @", myfilename );
 
// No files generated in correspond directory now
 
[Nskeyedarchiver archiverootobject: persistentarray tofile: myfilename];
// Now the myfile. rtf is generated
 
// Override point for customization after application launch
[Window makekeyandvisible];
}

 

The second parameter of nssearchpathfordirectoriesindomains () is an enumeration value. In the author's test code, only nsuserdomainmask and nsalldomainsmask can obtain the number of directories as 1 and the remaining values as 0, the output is as follows:

[Session started at 21:30:08 + 0800.]
21:30:10. 516 persistentexample [763: 207] path number is: 1
21:30:10. 518 persistentexample [763: 207] 0 path is:/users/sundfsun2009/library/Application Support/iPhone simulator/user/applications/C93DC783-F137-4660-AE5A-08C3E11C774B/Documents
21:30:10. 521 persistentexample [763: 207] myfile's path is:/users/sundfsun2009/library/Application Support/iPhone simulator/user/applications/C93DC783-F137-4660-AE5A-08C3E11C774B/documents/myfile. rtf
Terminating in response to springboard's termination.

[Session started at 21:32:27 + 0800.]
21:32:30. 091 persistentexample [803: 207] path number is: 1
21:32:30. 092 persistentexample [803: 207] 0 path is:/users/sundfsun2009/library/Application Support/iPhone simulator/user/applications/763e6772-e754-452f-8532-80c2ce4466b5/sources ents
21:32:30. 100 persistentexample [803: 207] myfile's path is:/users/sundfsun2009/library/Application Support/iPhone simulator/user/applications/documents/myfile. rtf
Terminating in response to springboard's termination.

The printed result is as follows. The directory names of the numeric string generated each time the application starts are different. Before calling the [nskeyedarchiver archiverootobject: persistentarray tofile: myfilename] method, the file myfile. rtf is generated and the corresponding file is generated only after this method is called.

Next, we need to read the data from the attribute list. In the code above, I use nsarray to save the data. However, in most applications, the data size is not fixed. In this case, you need to use nsmutalbearray to dynamically Save the data. The code optimization is as follows:

-(Void) applicationdidfinishlaunching :( uiapplication *) Application {

Nsstring * myfilename;
// Archive
{
Nsstring * strone = @ "persistent data1 ";
Nsstring * strtwo = @ "persistent data 2 ";

Nsmutablearray * persistentarray = [[nsmutablearray alloc] init];
[Persistentarray addobject: strone];
[Persistentarray addobject: strtwo];

Nsarray * patharray = nssearchpathfordirectoriesindomains (nsdocumentdirectory, nsalldomainsmask, yes );

Int pathlen = [patharray count];
Nslog (@ "path number is: % d", pathlen );

Nsstring * filepath;

For (INT I = 0; I <pathlen; I ++)
{
Filepath = [patharray objectatindex: I];

Nslog (@ "% d path is: % @", I, filepath );
}

Myfilename = [filepath stringbyappendingpathcomponent: @ "myfile. rtf"];

Nslog (@ "myfile's path is: % @", myfilename );

[Nskeyedarchiver archiverootobject: persistentarray tofile: myfilename];
}
 
// Unarchive
{
Nsarray * unarchivearray = [nskeyedunarchiver unarchiveobjectwithfile: myfilename];
Nsstring * unstrone = [unarchivearray objectatindex: 0];
Nsstring * unstrtwo = [unarchivearray objectatindex: 1];

Nslog (@ "unstrone =%@, unstrtwo =%@", unstrone, unstrtwo );
}
 
 
// Override point for customization after application launch
[Window makekeyandvisible];
}

 

The output result is as follows:

 

[Session started at 22:41:57 + 0800.]
22:41:59. 344 persistentexample [1082: 207] path number is: 1
22:41:59. 346 persistentexample [1082: 207] 0 path is:/users/sundfsun2009/library/Application Support/iPhone simulator/user/applications/055cd17c-864e-4a83-abf0-5f01ee85bd5a/Documents
22:41:59. 355 persistentexample [1082: 207] myfile's path is:/users/sundfsun2009/library/Application Support/iPhone simulator/user/applications/documents/myfile. rtf
22:41:59. 357 persistentexample [1082: 207] unstrone = persistent data1, unstrtwo = persistent data 2
Terminating in response to springboard's termination.

From the figure above, we can see that there is also a tmp directory in the directory. Readers can also save the data in the tmp directory and obtain this directory using the nstemporarydirectory () method.

Iii. Embedded Database (sqlite3)

Persistent data in Embedded databases is stored in the iPhone's embedded database system sqlite3. In essence, database persistence is based on file persistence.
To use the embedded database sqlite3, you must first load its dynamic library libsqlite3.dylib, which is located in the/xcode3.1.4/platforms/iphoneos. Platform/developer/sdks/iphoneos3.1.sdk/usr/lib directory. Right-click the framework folder and select "adding-> existing files..." to locate the Directory and load it to the folder.

First, modify the header file as follows:

# Import <uikit/uikit. h>

# Include "sqlite3.h"
# Define kfilename @ "mydb. SQL"

@ Interface persistentexampleappdelegate: nsobject <uiapplicationdelegate> {
Sqlite3 * database;
Uiwindow * window;
}

@ Property (nonatomic, retain) iboutlet uiwindow * window;

@ End

-(Void) applicationdidfinishlaunching :( uiapplication *) Application {
 
Nsarray * Path = nssearchpathfordirectoriesindomains (nsdocumentdirectory, nsuserdomainmask, yes );
Nsstring * paths = [[path objectatindex: 0] stringbyappendingpathcomponent: kfilename];
 
Nsfilemanager * filemanager = [nsfilemanager defaultmanager];
Bool findfile = [filemanager fileexistsatpath: Paths];
 
Nslog (@ "Database File Path = % @", paths );
 
// If the database file is found
If (findfile)
{
Nslog (@ "database file have already existed .");
 
If (sqlite3_open ([paths utf8string], & database )! = Sqlite_ OK) // failed to open the database
{
Sqlite3_close (database );
Nsassert (0, @ "failed to open database ");
}
} Else
{
Nslog (@ "database file does not exsit! ");
If (sqlite3_open ([paths utf8string], & database )! = Sqlite_ OK) // failed to open the database
{
Sqlite3_close (database );
Nsassert (0, @ "failed to open database ");
}
}
 
Char * errormsg;

 

// Create a table
Nsstring * createsql = @ "create table if not exists fields (row integer primary key, field_data text );";

If (sqlite3_exec (Database, [createsql utf8string], null, null, & errormsg )! = Sqlite_ OK)
{
Sqlite3_close (database );
Nsassert1 (0, @ "error creating table: % s", errormsg );
}
 
Nsstring * strone = @ "persistent data1 ";
Nsstring * strtwo = @ "persistent data 2 ";
 
Nsmutablearray * persistentarray = [[nsmutablearray alloc] init];
[Persistentarray addobject: strone];
[Persistentarray addobject: strtwo];
 
For (INT I = 0; I <[persistentarray count]; I ++ ){
Nsstring * updatasql = [[nsstring alloc] initwithformat: @ "insert or replace

Fields (row, field_data) values (% d, '% @'); ", I, [persistentarray objectatindex: I];

Char * errormsg;
If (sqlite3_exec (Database, [updatasql utf8string], null, null, & errormsg)

! = Sqlite_ OK)
{
Sqlite3_close (database );
Nsassert (0, @ "failed to open database ");
}
}
 
// Unarchive
Nsstring * query = @ "select row, field_data from fields order by row"; // query table data
Sqlite3_stmt * statement;
If (sqlite3_prepare_v2 (Database, [query utf8string],-1, & statement, nil)

= Sqlite_ OK)
{
While (sqlite3_step (statement) = sqlite_row)
{
Int ROW = sqlite3_column_int (statement, 0 );
Char * rowdata = (char *) sqlite3_column_text (statement, 1 );

Nsstring * fieldname = [[nsstring alloc] initwithformat: @ "show % d", row];
Nsstring * fieldvalue = [[nsstring alloc] initwithuf8string: rowdata];

Nslog (@ "fieldname is: % @, fieldvalue is: % @", fieldname, fieldvalue );

[Fieldname release];
[Fieldvalue release];
}
Sqlite3_finalize (statement );
}
 
// Override point for customization after application launch
[Window makekeyandvisible];
}

In the above Code, we use
Nsfilemanager * filemanager = [nsfilemanager defaultmanager];
Bool findfile = [filemanager fileexistsatpath: Paths];
In most cases, it is unnecessary to determine whether the database file already exists. The sqlite3_open () method will automatically help us determine whether the database file exists, if not, create a database file.

IV. Other Methods

In addition to the above three methods to save persistent data, we can also save persistent data by writing files to the disk.

-(Void) applicationdidfinishlaunching :( uiapplication *) Application {

 
Nsstring * strone = @ "persistent data1 ";
Nsstring * strtwo = @ "persistent data 2 ";
 
Nsmutablearray * persistentarray = [[nsmutablearray alloc] init];
[Persistentarray addobject: strone];
[Persistentarray addobject: strtwo];
 
 
 
Nsarray * filepatharray = nssearchpathfordirectoriesindomains (nsdocumentdirectory, nsuserdomainmask, yes );
Nsstring * filepath =

-[[Filepatharray objectatindex: 0] stringbyappendingpathcomponent: @ "mydatas. plist"];
 
[[Nsarray arraywithobjects: persistentarray, nil] writetofile: filepath atomically: No];
 
// Load
Nsmutablearray * savedataarray = [[nsmutablearray alloc] init];
If ([[nsfilemanager defaultmanager] fileexistsatpath: filepath])
Savedataarray = [nsmutablearray arraywithcontentsoffile: filepath];
Else
Savedataarray = [nsmutablearray arraywithcontentsoffile: [nsbundle

-Mainbundle] pathforresource: @ "savedatas" oftype: @ "plist"];

-
Nsarray * strarray = [savedataarray objectatindex: 0];
 
Nsstring * unstrone = [strarray objectatindex: 0];
Nsstring * unstrtwo = [strarray objectatindex: 1];

// Override point for customization after application launch
[Window makekeyandvisible];
}

 

Reprinted from: http://blog.csdn.net/dongfengsun/archive/2009/11/11/4799249.aspx

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.