ios下主要有四种数据持久化方法:
1.属性列表
2.对象归档
3.SQLite3
4.CoreData
下面分别简单介绍这四种方法。
1.属性列表
将支持序列化的object C对象add至NSArray或NSDictionary中,然后调用这两个对象的writeToFile方法,例如:
[MyArray writeToFile:@"/filepath/file.plist" atomically=YES]
在object C中,支持序列化的对象有:
NSArray
NSMutableArray
NSDictionary
NSMutableDictionary
NSData
NSMutableData
NSString
NSMutableString
NSNumber
NSDate
因此,属性列表方法有个缺点,就是不能将自定义的对象持久化.因为自定义对象不支持序列化.
2.对象归档
要使用对象归档,对象必须实现NSCoding协议.大部分Object C对象都符合NSCoding协议,也可以在自定义对象中实现NSCoding协议,要实现NSCoding协议,只许实现两个方法:
- (void) encodeWithCoder:(NSCoder *)encoder 与 -(void)initWithCoder:(NSCoder *)encoder
同时,建议对象也同时实现NSCopying协议,该协议允许复制对象,要实现NSCopying协议须实现 -(id)copyWithZone:(NSZone *)zone 方法 。
对对象归档的主要步骤如下:
NSMutableData *data = [[NSMutableData alloc] init]; //建一个NSMutableData对象,用于包含编码数据。
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
[archiver encodeObject:myObject forKey:myKey]; //使用键/值编码将对象归档至data中
[archiver finishEncoding];
BOOL success = [data writeToFile:@"filepath/myfile.plist" atomically:YES]; //将NSMutableData写入文件系统
[unarchiver release];
[data release];
[myObject release];
对对象解档的主要步骤如下:
NSData *data = [[NSMutableData alloc]initWithContentsOfFile: @"filepath/myfile.plist" ];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
MyObject *myObject = [unarchiver decodeObjectForKey:myKey];
[unarchiver finishDecoding];
[unarchiver release];
[data release];
[myObject release];
[archiver release];
[data release];
3. SQLite3
SQLite3是Iphone的嵌入式SQL数据库。如果应用程序需要所有对象中符合某些条件的某个对象,SQLite可执行该操作,而避免将所有对象都加载到内存,减小开销。
在ios中,打开和关闭数据库的方法如下:
sqlite3 *database;
int result = sqlite3_open(pathString, &database);
sqlite3_close(database);
sqlite3是采用可移植的C(而非Objective C)写的,因此pathString必须为string类而不能为NSString,必须将NSString转为string:
char *stringPath = [pathString UTF8String];
以下是几个数据库操作的例子,包括create table, select from table和 insert into 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);
}
NSString *query = @"SELECT ROW, FIELD_DATA FROM FIELDS ORDER BY ROW";
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); //index 0 代表ROW域
char *rowData = (char *)sqlite3_column_text(statement, 1);
NSString *fieldName = [[NSString alloc]
initWithFormat:@"field%d", row];
NSString *fieldValue = [[NSString alloc]
initWithUTF8String:rowData];
}
sqlite3_finalize(statement);
}
char *update = "INSERT OR REPLACE INTO FIELDS (ROW, FIELD_DATA) VALUES (?, ?);";
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(database, update, -1, &stmt, nil) == SQLITE_OK) {
sqlite3_bind_int(stmt, 1, rowNum); //将rowNum绑定之第一个问号
sqlite3_bind_text(stmt, 2, [field.text UTF8String], -1, NULL);
}
if (sqlite3_step(stmt) != SQLITE_DONE)
NSAssert1(0, @"Error updating table: %s", errorMsg);
sqlite3_finalize(stmt);
4. Core Data
尽管Core Data也是使用SQLite保存数据,但是使用它不需要编写任何SQL语句,程序员只需操作各个对象,剩下的工作交给Core Data,这个有点类似于JPA。
要使用Core Data,需要在Xcode中的数据模型编辑器中设计好各个实体以及定义好他们的属性和关系。之后,通过操作这些对象,结合Core Data完成数据的持久化:
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSError *error;
NSString *fieldName = [NSString stringWithFormat:@"line%d", i];
UITextField *theField = [self valueForKey:fieldName];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Line"
inManagedObjectContext:context]; //创建描述语句,需求Line对象。类似于在数据库中限定为Line表。
[request setEntity:entityDescription];
NSPredicate *pred = [NSPredicate predicateWithFormat:@"(lineNum = %d)", i]; //创建限制性语句,类似于SQL语句中的 where lineNum = i
[request setPredicate:pred];
NSManagedObject *theLine = nil;
NSArray *objects = [context executeFetchRequest:request error:&error];
if (objects == nil){
NSLog(@"There was an error!");
// Do whatever error handling is appropriate
}
if ([objects count] > 0) //如果符合条件的object存在,则取出
theLine = [objects objectAtIndex:0];
else //如果不存在,则插入一个新的.
theLine = [NSEntityDescription insertNewObjectForEntityForName:@"Line"
inManagedObjectContext:context];
[theLine setValue:[NSNumber numberWithInt:i] forKey:@"lineNum"]; //设置这个object的属性,coredata会自动将其写入sqlite
[theLine setValue:theField.text forKey:@"lineText"];
[request release];
}
[context save:&error];
下面是其取数据的过程。
Core_Data_PersistenceAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Line"
inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
if (objects == nil)
{
NSLog(@"There was an error!");
// Do whatever error handling is appropriate
}
for (NSManagedObject *oneObject in objects) //每一个对象在CoreData中都表示为一个NSManagedObject对象(类似于数据库表中的每一行),他的属性通过键/值 方式获取
{
NSNumber *lineNum = [oneObject valueForKey:@"lineNum"];
NSString *lineText = [oneObject valueForKey:@"lineText"];
}
[request release];