Four data persistence methods in ios development [1. attribute list and archiving] And ios4
Permanent storage in iOS, that is, data will not be lost when the device is shut down and restarted or the application is closed. In actual application development, data is often stored permanently, so that users can see the results and traces of their changes after the application is started again. In ios development, we need the data persistence technology, and we also need to constantly improve the data persistence development technology in actual development work and learning.
This article introduces four data persistence methods:
1. attribute list
2. Object archiving and archive
3. Use of database SQLite3
4. Use of Core Data
Of course, in iOS development, the persistent data method is not limited to the above four methods. You can also use the left blog:Ios development-application settings and user default settings [1. Use of bundle]This blog introduces how to store application settings;
You can also useTraditional C language I/O calls (such as fopen () read and write data, You can useCocoa underlying file management toolBut both of these methods require developers to write a lot of code. This article will not introduce them. If you need them, you can find them online.
Before introducing four persistent storage methods, we need to introduce three related folders:
- Documents: The application stores data in this folder, except for preference settings based on NSUserDefaults;
- Library: preference settings based on NSUserDefaults are stored in the Library/Preferences folder;
- Tmp: temporary files are stored. When the iOS device performs synchronization, iTunes does not back up the files in this folder, but when these files are not needed, applications need to delete these files in tmp to avoid occupying file system space;
How to get it?
1. Get the Documents directory
Because the data storage used in iOS is a sandbox mechanism, to read and write files, we need to call the C function "NSSearchPathForDirectoriesInDomains ()" to find various directories, (this C function can be shared based on Cocoa on Mac OS X)
For example, the code used to retrieve the paths of the Documents directory is as follows:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);NSString *pathDirectory = [paths objectAtIndex:0];
The first constant NSDocumentDirectory indicates that we are looking for the directory path, and the second constant NSUserDomainMask indicates that we want to restrict the search in the sandbox of the application; (in Mac OS X, this constant indicates that we want this function to view the user's main directory, so this name will be available ;)
The returned data is paths. Why is index 0 the required Documents directory? Because each application has only one Documents directory, only one directory meets this condition;
Next, we can add a string to the end of the retrieved directory pathDirectory to create a file name, as shown below:
NSString * filename = [pathDirectory stringByAppendingPathComponent: @ "data.txt"];
// Note that it is stringByAppendingPathComponent. Do not spell it incorrectly.
In this case, we can create, read, and write the filename string.
2. Obtain the tmp directory:
You can use the Foundation function of NSTemporaryDirectory () to return a string containing the complete path to the temporary directory of the application. Similarly, you can create a file path pointing to the directory by attaching a file name to the end.
NSString *tmpPath = NSTemporaryDirectory();NSString *temFile = [tmpPath stringByAppendingPathComponent:@"tempFile.txt"];
-------------------------------------
The following describes how to implement the data persistence method:
I. attribute list
In [1. Use of bundle], we use the attribute List to specify the default settings of the application and the corresponding data storage, and it is convenient to use Xcode or the Property List Editor application to manually edit them, as long as the dictionary or data contains a specific serializable object, you can write the NSDictionary and NSArray instances to the attribute list or create the corresponding object from the attribute list;
What is a serialized object?
Serialized objects is an object that can be converted to a byte stream for storage in a file or transmitted over the network;
Although any object can be serialized, only some specific objects can be placed in a collection class (such as NSArray, NSMutableArray, NSDictionary, and NSData, you can use the methods of this collection class to store the attribute list. You can also use the archive method to store other objects (we will introduce the object archive and archive in detail ).
Then we started to build the first simple application to store data using the attribute list:
The specific function is [1]. You can enter data in four text boxes. When the application exits, these fields are saved to the attribute list, and re-load and restore the last data at the next startup;
Figure 1]
In Xcode, use the Single View Application template to create a new project named persistence1.
Drag four labels and four text box controls in "Main. storyboard", drag and align the labels and text boxes, and modify the label text in sequence, as shown in Figure 1."ViewController. h"To add an array containing four text boxes"LineFields":
#import <UIKit/UIKit.h>@interface ViewController : UIViewController@property (strong,nonatomic)IBOutletCollection(UITextField)NSArray *lineFields;@end
Open the auxiliary editor and use the control key to connect the four text boxes to the lineFields array. Make sure that the connection order is from top to bottom!
In the project Navigation Pane, click"ViewController. m", Add the following code @ ImplementationAnd@ EndIn the middle, this method will always be called later:
// Obtain the full path of the data file in the attribute list path, dataFilepath // you can call this method for the code to load and save the data. -(NSString *) dataFilepath {NSArray * paths = require (NSDocumentDirectory, NSUserDomainMask, YES); NSString * pathDirectory = [paths objectAtIndex: 0]; return [pathDirectory stringByAppendingPathComponent: @ "data.txt"];}
Next, add the code in viewDidload and add the corresponding responder method:
-(Void) viewDidLoad {[super viewDidLoad]; NSString * filePath = [self dataFilepath]; // determine whether an attribute list file exists if ([[NSFileManager ultultmanager] fileExistsAtPath: filePath]) {// If yes, assign the data value to the text box NSArray * ar = [[NSArray alloc] initWithContentsOfFile: filePath]; for (int I = 0; I <4; I ++) {UITextField * textField = self. lineFields [I]; textField. text = ar [I] ;}}// if the application enters the background: UIApplication * app = [UIApplication sharedApplic Ation]; [[nsicationicationcenter defacenter center] addObserver: self selector: @ selector (applicationWillResignActiveNotification :) name: jsonobject: app];} // when the application enters the background, execute:-(void) applicationWillResignActiveNotification :( NSNotification *) notification {NSString * pathFile = [self dataFilepath]; // we use a convenient method instead of an iterative array, using the valueForKey method in the NSarrry class, assign an array containing @ "text" in lineFields to array. NSArray * array = [self. lineFields valueForKey: @ "text"]; // write a string array to a file. [Array writeToFile: pathFile atomically: YES];}
This code first checks whether the data file in the full path exists and does not exist;
If yes, the objects in the array are copied to the four text boxes. The data can be assigned to the text box according to the connection sequence between the array "lineFields" and the text box.
Data is stored before the application ends or enters the background. Therefore, we use the notification center to subscribe to theUIApplicationWillResignActiveNotification"Notification, and implements"ApplicationWillResignActiveNotification.
This method is called when the user presses the "Home Key" of the mobile phone or another event (such as a call) causes the application to enter the background, write the string array into the created attribute list file.
Okay, we have done it.GUIThe basic design of the interface and code programming are completed. Next, press "command + R" to run it;
If there are no other problems, we can type 4 text boxes, click the Home Key, double-click the Home key, or terminate the application in Xcode to exit the simulator (equivalent to restarting the mobile phone ), to verify that the data is permanently saved in the application.
Summary: property list serialization is very practical and relatively simple, but it also has some limitations, that is, only a small part of objects can be saved in the property list, next we will introduce the powerful archive object data storage method;
Ii. Archive and archive Model Objects
As described in the previous attribute list, archiving is another form of serialization. However, it is powerful because it is a more common data storage type that can be implemented by any object;
We need to implement the NSCoding and NSCopying protocols in the Development of archiving and file decoding. It must be noted that scalar (such as int or float) most of the Foundation and Cocoa Touch classes follow the NSCoding protocol (with exceptions, for example, UIImage does not follow). Therefore, most classes are easier to implement archive operations;
1. Follow the NSCoding protocol and NSCopying Protocol
The NSCoding Protocol declares two methods: one is to encode the object into the archive, and the other is to decode the archive to restore the previously archived object, similar to NSUserDefaults, you can also use KVC to encode and decode objects and native data types (such as int and float)
The NSCopying protocol is used to allow copying objects, making it flexible to use data model objects;
2. Archive and archive
Archive: Create an NSKeyedArchiver instance to archive the object to an NSMutableData instance. Then, use the key/code to archive the required object, and finally inform you that it is complete and write it to the file system;
Solution: similar to the archive object step, create an NSData instance to load data, create an NSKeyedUnarchiver instance, decode the data, and then use the previous key to read the object, finally, inform the program that the archive is completed;
This is a bit dry ~ Go to the Code:
A. Create a "linePesist" Class
In Xcode, use the Single View Application template to create a new project namedPersistence2That's right. It's the same as the application template in the property list.
However, you need to create a New File, press command + N, or select New> New File from the File menu. After the new file wizard appears, select Cocoa Touch, select Objective-C class, and click Next to name the class
"LinePesist", Select NSObject in the" Subclass of "column, click Next, and then click Create. This class serves as our data model and will be used to store data in the dictionary of the attribute list application.
Click"LinePesist. h", Modify the Code as follows:
# Import <Foundation/Foundation. h> // follow the NSCoding and NSCopying protocols @ interface linePesist: NSObject <NSCoding, NSCopying> @ property (nonatomic, copy) NSArray * array; @ end
This is a simple data model with arrays. Arrays can be used to place data fields in text boxes.
Next, we willLinePesist. m"Edit:
# Import "linePesist. h "# define CodeStr @" CodeStr "// The key name @ implementation linePesist/* used to archive the archive file. By following the NSCoding and NSCoping methods, create an archive data object. */# Pragma mark -- Coding // encoding-(void) encodeWithCoder :( NSCoder *) ACO {[ACO encodeObject: self. array forKey: CodeStr];} // decoding-(id) initWithCoder :( NSCoder *) aDecoder {self = [super init]; if (self) {self. array = [aDecoder decodeObjectForKey: CodeStr];} return self ;}# pragma mark -- Coping-(id) copyWithZone :( NSZone *) zone {linePesist * copy = [[[self class] allocWithZone: zone] init]; NSMutableArray * muAr = [[NSMutableArray alloc] init]; for (id line in self. array) {[muAr addObject: [line copyWithZone: zone];} copy. array = muAr; return copy;} @ end
Use the predefined "CodeStr" as the key for encoding and decoding, store the strings of the four text boxes, and then use the same "CodeStr" key for decoding, copy the four strings to the linePesist object created by copyWithZone;
B. "ViewController" class implementation
After common archive data objects, we can use them for persistent storage. Click "ViewController. m" to edit the code.
# Import "ViewController. h "# import" linePesist. h "// import data model class # define CodeString @" CodeString "@ implementation ViewController-(NSString *) dataFile {NSArray * ar = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES ); NSString * fielpath = [ar objectAtIndex: 0]; return [pathDirectory stringByAppendingPathComponent: @ "data.txt"]; return [fielpath stringByAppendingPathComponent: @ "data. Archive "]; // modify the suffix to avoid repeating the file created in the attribute list and loading it into the old file. No need to look up the dictionary .. Archive table archive}-(void) viewDidLoad {[super viewDidLoad]; NSString * filepath = [self dataFile]; NSLog (@ "% @", filepath ); if ([[NSFileManager defaultManager] fileExistsAtPath: filepath]) {NSArray * ar = [[NSArray alloc] initWithContentsOfFile: filePath]; for (int I = 0; I <4; I ++) {UITextField * textField = self. lineFields [I]; textField. text = ar [I];} // create two instances NSData * data = [[NSData alloc] initWithContentsOfFile: fi Lepath]; NSKeyedUnarchiver * unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData: data]; // read archived objects. Assign the value to linepesist linePesist * linepesist = [unarchiver decodeObjectForKey: CodeString]; [unarchiver finishDecoding]; // complete the archive for (int I = 0; I <4; I ++) {// assign the archive data to the text box UITextField * textField = self. fourLines [I]; textField. text = linepesist. array [I]; // remember it. text} UIApplication * app = [UIApplication sharedApplication]; [[nsicationcenter center defacenter center] addObserver: self selector: @ selector (applicationWill ResignActiveNotification :) name: UIApplicationWillResignActiveNotification object: app];} // return the application to the background, archive and write data to the file-(void) applicationWillResignActiveNotification :( NSNotification *) notfication {NSArray * array = [self. lineFields valueForKey: @ "text"]; [array writeToFile: pathFile atomically: YES]; NSString * pathField = [self dataFile]; linePesist * linepesit = [[linePesist alloc] init]; linepesit. array = [self. fo UrLines valueForKey: @ "text"]; // create two instances NSMutableData * data = [[NSMutableData alloc] init]; NSKeyedArchiver * archiver = [[NSKeyedArchiver alloc] alias: data]; // use key/value encoding to archive objects to be included in the archive. [Archiver encodeObject: linepesit forKey: CodeString]; [archiver finishEncoding]; // like the attribute list, you need to write the file at the end, because the attribute list and archive are both serialized, finally, you still need to write the file. [Data writeToFile: pathField atomically: YES] ;}@ end
In addition to data storage,GUIThe interface is consistent with the previous version. Run the persistence application of this version. The effect should be the same as when we run the attribute list.
Now, we will introduce the attribute list and archive Object Storage Methods. What are the differences between them... the most obvious difference is that there is more code to archive, but the archive will be very scalable, at least from the code above, it is.
In the next section, we will introduce the following two methods:Application of Database SQLite3,Use of Core Data;