Several Common Data Storage Methods for iOS and several data storage methods for ios
Since the beginning of the line, I was not very familiar with data persistence, especially when using a database to store a large amount of data. I would like to summarize it here for future reference.
The following is a brief introduction:
1. NSUserDefaults
I feel that the most common small amount of data, attributes, such as accounts and passwords, is suitable for storing lightweight local data (I personally think this is relatively simple)
NSUserDefaults supports the NSNumber (Integer, Float, Double), NSString, NSDate, NSArray, NSDictionary, and BOOL data formats.
It is easier to understand the Code directly:
// Test data NSArray * myArray = [NSArray arrayWithObjects: @ "hello", @ "world", nil]; NSDictionary * myDictionary = [NSDictionary Syntax: [NSArray arrayWithObjects: @ "enuo", @ "20", nil] forKeys: [NSArray arrayWithObjects: @ "name", @ "age", nil]; // save it to [[NSUserDefaults standardUserDefaults] setObject: myArray forKey: @ "arry"]; [[NSUserDefaults standardUserDefaults] setObject: myDictionary forKey: @ "dict"]; // We recommend that you synchronize the data to the disk, but not the required [[NSUserDefaults standardUserDefaults] synchronize]; // read NSArray * arr = [[NSUserDefaults standardUserDefaults] objectForKey: @ "arry"]; NSDictionary * dict = [[NSUserDefaults standardUserDefaults] objectForKey: @ "dict"]; NSLog (@ "------ % @ ---- \ n ----- % @------", arr, dict); // clear data [[NSUserDefaults standardUserDefaults] removeObjectForKey: @ "keyName"];
Suggestion: [NSUserDefaults standardUserDefaults] You can define a global macro in the project to make it easier to use.
2. Archiving
The purpose is to store organized datasets for a long time.
(1) Simple archiving method, but only one object can be stored.
// (1) archive NSArray * array = [NSArray arrayWithObjects: @ 1, @ 2, @ 3, nil]; NSString * filePath = [NSHomeDirectory () stringByAppendingString: @ "testFile. plist "]; BOOL success = [NSKeyedArchiver archiveRootObject: array toFile: filePath]; NSLog (@" % d ", success); NSLog (@" % @ ", filePath ); // (2) reverse archive NSString * filePath = [NSHomeDirectory () stringByAppendingString: @ "testFile. plist "]; id OUTarray = [NSKeyedUnarchiver unarchiveObjectWithFile: filePath]; NSLog (@" % @ ", OUTarray );
(2) You can archive multiple objects into one file.
// (1) archive NSMutableArray * arrayArchiver = [NSMutableArray arrayWithObjects: @ "BigDragon", @ "BigBiao", @ "BigBaby", nil]; NSMutableData * data = [NSMutableData data]; optional * archiver = [[NSKeyedArchiver alloc] encoding: data]; // encode [archiver encodeObject: arrayArchiver forKey: @ "array"]; [archiver encodeObject: @ "Jason's friends" forKey: @ "name"]; // After encoding, the object is stored in data. [Archiver finishEncoding]; NSString * filePathtwo = [NSHomeDirectory () stringByAppendingPathComponent: @ "arraytwo. plist "]; BOOL successtwo = [data writeToFile: filePathtwo atomically: YES]; NSLog (@" ------ % d ", successtwo); // (2) back-archive NSString * filePathtwo = [NSHomeDirectory () stringByAppendingPathComponent: @ "arraytwo. plist "]; // read the archived data NSData * dataUnarchiver = [[NSData alloc] initWithContentsOfFile: filePathtwo]; // create an archive object, perform anti-Archive Export * unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData: dataUnarchiver]; // The Anti-archive NSArray * arrayUnarchiver = [unarchiver decodeObjectForKey: @ "array"]; NSLog (@ "---- % @", arrayUnarchiver); NSString * nameUnarchiver = [unarchiver decodeObjectForKey: @ "name"]; NSLog (@ "----- % @", nameUnarchiver );
(3) use the tool class (it is relatively convenient to use the tool class if archive is used)
Create a tool class and a Person class first.
Person. h
# Import <Foundation/Foundation. h> @ interface Person: NSObject <NSCoding> // The NSCoding Protocol @ property (nonatomic, strong) NSString * name is required; // The Archive type @ property (nonatomic, assign) NSInteger age; @ property (nonatomic, strong) NSString * gender;-(NSString *) description; @ end
Person. m
/** The class corresponding to this object must provide encodeWithCoder: And initWithCoder: method. The previous method tells the system how to encode the object, and the next method tells the system how to decode the object * // The Archive method-(void) encodeWithCoder :( NSCoder *) ecoder {[ecoder encodeObject: self. name forKey: @ "name"]; [ecoder encodeInteger: self. age forKey: @ "age"]; [ecoder encodeObject: self. gender forKey: @ "gender"];} // The Archive method-(instancetype) initWithCoder :( NSCoder *) aDecoder {self = [super init]; if (self! = Nil) {self. name = [aDecoder decodeObjectForKey: @ "name"]; self. age = [aDecoder decodeIntegerForKey: @ "age"]; self. gender = [aDecoder decodeObjectForKey: @ "gender"];} return self;}-(NSString *) description {NSString * string = [NSString stringWithFormat: @ "% @ \ n % ld \ n % @", self. name, self. age, self. gender]; return string ;}
When using the controller:
Person * person = [[Person alloc] init]; person. name = @ "rose"; person. age = 25; person. gender = @ "man"; // archive, call the archive method NSString * filePath3 = [NSHomeDirectory () stringByAppendingString: @ "person. plist "]; BOOL success3 = [NSKeyedArchiver archiveRootObject: person toFile: filePath3]; NSLog (@" =====% d ", success3); // archive, call the anti-archive method Person * per = [NSKeyedUnarchiver unarchiveObjectWithFile: filePath3]; NSLog (@ "======%@", per );
3. Write files
Main steps:
// Step 1: Obtain the path of the file to be saved: (permanently saved on disk) // The relative directory of the file storage NSArray * filePaths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES ); NSString * path = filePaths. firstObject; // Step 2: generate the file in this path: NSString * FileName = [path stringByAppendingPathComponent: @ "flieName"]; // fileName is the file name to save the file
// Step 3: write data to the file:
NSData * data; [data writeToFile: FileName atomically: YES]; // write NSData-type object data to a file named FileName
// Finally: read data from the file: NSData * outdata = [NSData dataWithContentsOfFile: FileName options: 0 error: NULL]; // read data from FileName
Below are a few simple examples.
# Pragma mark -- 1. string write // NSString * strfilepath = [path stringByAppendingPathComponent: @ "str. text "]; NSString * strfilepath = [path stringByAppendingString: @"/text. text "]; NSString * INstr = @" string Write File "; [INstr writeToFile: strfilepath atomically: YES encoding: NSUTF8StringEncoding error: nil]; // read the file NSString * OUTstr = [[NSString alloc] initWithContentsOfFile: strfilepath encoding: NSUTF8StringEncoding error: nil]; NSLog (@ "---- % @ -----", OUTstr ); # pragma mark-2. Write an array object to a file // construct the storage path NSString * arrypath = [path stringByAppendingPathComponent: @ "arry. plist "]; NSArray * INarr = @ [@" hahah ", @" hehhe ", @" heihei "]; [INarr writeToFile: arrypath atomically: YES]; // read the file NSArray * outarr = [[NSArray array] initWithContentsOfFile: arrypath]; NSLog (@ "---- % @ -----", outarr ); # pragma mark-3. NSString * dictpath = [path stringByAppendingPathComponent: @ "dict. plist "]; NSDictionary * dict ={ @" name ": @" liuwenqiang ", @" Age ": @" 25 ", @" Occupation ": @ "ios"}; [dict writeToFile: dictpath atomically: YES]; // read the file NSDictionary * OUTdict = [[NSDictionary alloc] initWithContentsOfFile: dictpath]; NSLog (@ "---- % @ -----", OUTdict); # pragma mark-4. The binary object is written into the file NSString * datapath = [path stringByAppendingPathComponent: @ "song. m4a "]; UIImage * image = [UIImage imageNamed: @" image "]; NSData * imagedata = UIImageJPEGRepresentation (image, 1); [imagedata writeToFile: datapath atomically: YES]; // read the file NSData * OUTdata = [[NSData alloc] initWithContentsOfFile: datapath]; NSLog (@ "---- % @ -----", OUTdata );
4. Database
For large data storage, the above method is obviously not applicable. It is time to use the database. I am using a third-party database FMDB in the project. I personally feel that it is easy to use, it is easy to use.
So what is large data? I think it is the type of list in the app. Because the list data volume is quite large, if there is a list chart in the list like our application, that's even bigger.
Before reading the database, it was hard to understand and learn, but it was not so difficult to understand. (the following method must be in the tool class. h, so that the controller can be tuned)
Before performing this operation, you need to download an FMDB file and attach it to the project: FMDB
Create a tool class fmbdTool first
(1) create databases and tables
@ Implementation FmdbTool {FMDatabase * db;}-(NSString *) createFMDBTable :( NSString *) type {NSString * str; // 1. obtain the database file path NSString * doctorpath = [NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; NSString * filePath = [doctorpath stringbyappendpathcomponent: @ "doctor. sqlite "]; // NSLog (@" ------- path ---- % @ ------- ", filePath); // 2. obtain database db = [FMDatabase databaseWithPath: filePath]; // 3. open Database if ([db open]) {// 4. create table bool result; if ([type isinclutostring: @ "doctor"]) {result = [db executeUpdate: @ "create table if not exists t_doctor (id integer primary key autoincrement, doctordict blob not null, page_ID integer not null, datacount text not null) "];} if (result) {// NSLog (@ "==== table creation succeeded -------- type ==%@", type); str = @ "yes ";} else {NSLog (@ "=== table creation failed"); str = @ "no" ;}} else {NSLog (@ "faile to create a FMDB "); str = @ "no";} return str ;}
In my project, there are a lot of lists for data storage, so I added a parameter type in the method of creating a database to create a table for each page to be stored, and put all the tables
Doctor. sqlite in this library.
When creating a table, you first need to [db open] open the database. The returned data type is bool. If it is true, create a table.
result = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_doctor (id integer PRIMARY KEY AUTOINCREMENT,doctordict blob NOT NULL,page_ID integer NOT NULL,datacount text NOT NULL)"];
Doctordict is a digital data type, that is, the doctorInfoList field in the data returned by the background, so the doctordict type is blob. This field cannot be empty, so it is not null when creating a table.
The list has a paging request, so the page number is stored in the Table. page_ID integer not null. Datacount is the total number of pages in the list.
(2) Insert data
// Insert data-(void) addDataInsetTable :( NSArray *) doctorListArry page :( NSInteger) page datacount :( NSString *) datacount type :( NSString *) type {if ([db open]) {NSString * pagestr = [NSString stringWithFormat: @ "% ld", (long) page]; NSError * err = nil; NSData * jsonData = [NSJSONSerialization dataWithJSONObject: doctorListArry options: NSJSONWritingPrettyPrinted error: & err]; NSString * jsonStr = [[NSString alloc] initWit HData: jsonData encoding: NSUTF8StringEncoding]; if ([type is0000tostring: @ "doctor"]) {[db executeUpdate: @ "insert into t_doctor (doctordict, page_ID, datacount) VALUES (?,?,?); ", JsonStr, pagestr, datacount] ;}} [db open];}
Data can be inserted only after [db open.
Through this method, we can see that I can directly Insert the data returned to me by the background, responseObject [@ "doctorInfoList"] into the table,
Before insertion, convert the array to a json string. I used it here. The download address of JSONKit
(3). Fetch data
-(NSArray *)outdata:(NSString *)type{ NSArray *dataArr; NSMutableArray *aaarr = [[NSMutableArray alloc]init]; if ([db open]) { if ([type isEqualToString:@"doctor"]) { FMResultSet *res = [db executeQuery:@"SELECT * FROM t_doctor"]; while (res.next) { NSString *s = [res stringForColumn:@"doctordict"]; NSArray *aa = [s objectFromJSONString]; [aaarr addObjectsFromArray:aa]; dataArr = aaarr; } } } [db close]; return dataArr;}
// When the current page number is retrieved at this type-(NSString *) checkoutpage :( NSString *) type {NSString * str; if ([db open]) {FMResultSet * res = [db executeQuery: @ "SELECT * FROM t_activesecond where type =? ", Type]; while (res. next) {str = [res stringForColumn: @" page "] ;}} [db close]; return str ;}
(4). delete data
// Delete data-(void) deleteData :( NSString *) type {if ([db open]) {if ([type isEqualToString: @ "doctor"]) {NSString * deleteSql = [NSString stringWithFormat: @ "delete from t_doctor"]; [db executeUpdate: deleteSql] ;}} [db close];}
When I delete the data, I only deleted the data. I specified the table and did not directly Delete the database. For this reason, all the tables are in this database.
Write it here first. If anything is wrong, please point it out. Thank you.