一、plist 存储
//获取Plist文件的全路径NSString *path = [[NSBundle mainBundle] pathForResource:@"shops" ofType:@"plist"];//加载plist文件_shops = [NSArray arrayWithContentsOfFile:path];
2、属性列表——归档NSDictionary. 将数据封装成字典,将字典持久化到Documents/stu.plist文件中
NSMutableDictionary *dict = [NSMutableDictionary dictionary];[dict setObject:@"15013141314" forKey:@"phone"];[dict writeToFile:path atomically:YES];
3、属性列表——恢复NSDictionary; 读取Documents/stu.plist的内容,实例化NSDictionary.
NSMutableDictionary *dict = [NSMutableDictionary dictionary];[dict setObject:@"15013141314" forKey:@"phone"];[dict writeToFile:path atomically:YES];
二、UserDefaults ;偏好设置存储
写入需保存的设置
[[NSUserDefaults standardUserDefaults] setFloat:18.0f forKey:@"text_size"];
读取上次保存的设置
float textSize = [[NSUserDefaults standardUserDefaults] floatForKey:@"text_size"];
注意:IOS7之前UserDefaults设置数据时,不是立即写入可能还没有写入磁盘应用程序就终止了导致数据丢失,可以通过调用synchornize方法强制写入;
IOS7之后已经实现即时写入,可以省略此步
[defaults synchronize]; //'siŋkrənaiz
三、NSKeyedArchiver 归档存储
系统对象通过NSKeyedArchiver保存与读取数据
归档一个NSArray对象到Documents/array.archive
NSArray *array = [NSArray arrayWithObjects:@”a”,@”b”,nil];[NSKeyedArchiver archiveRootObject:array toFile:path];
恢复(解码)NSArray对象
NSArray *array = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
需要遵守
- (void)encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:self.name forKey:@"name"];
[encoder encodeInt:self.age forKey:@"age"];
[encoder encodeFloat:self.height forKey:@"height"];
}
- (id)initWithCoder:(NSCoder *)decoder {
self.name = [decoder decodeObjectForKey:@"name"];
self.age = [decoder decodeIntForKey:@"age"];
self.height = [decoder decodeFloatForKey:@"height"];
return self;
}
自定义对象通过NSKeyedArchiver保存与读取数据
1)归档(编码)
Person *person = [[[Person alloc] init] autorelease];person.name = @"MJ";
person.age = 27;
person.height = 1.83f;
[NSKeyedArchiver archiveRootObject:person toFile:path];
2)恢复(解码)
Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
3)注意
如果父类也遵守了NSCoding协议,应该在encodeWithCoder:方法中加上一句:
[super encodeWithCode:encode];
确保继承的实例变量也能被编码,即也能被归档,应该在initWithCoder:方法中加上一句:
self = [super initWithCoder:decoder];
确保继承的实例变量也能被解码,即也能被恢复.
利用归档实现深复制
//比如对一个Person对象进行深复制,临时存储person1的数据
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person1];
//解析data,生成一个新的Person对象
Student *person2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
//分别打印内存地址
NSLog(@"person1:0x%x", person1); // person1:0x7177a60
NSLog(@"person2:0x%x", person2); // person2:0x7177cf0
归档
NSKeyedArchiver专门用来做自定义对象归档
// 什么时候调用:当一个对象要归档的时候就会调用这个方法归档
// 作用:告诉苹果当前对象中哪些属性需要归档
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:_name forKey:@"name"];
[aCoder encodeInt:_age forKey:@"age"];
}
// 什么时候调用:当一个对象要解档的时候就会调用这个方法解档
// 作用:告诉苹果当前对象中哪些属性需要解档
// initWithCoder什么时候调用:只要解析一个文件的时候就会调用
- (id)initWithCoder:(NSCoder *)aDecoder
{
#warning [super initWithCoder]
if (self = [super init]) {
// 解档
// 注意一定要记得给成员属性赋值
_name = [aDecoder decodeObjectForKey:@"name"];
_age = [aDecoder decodeIntForKey:@"age"];
}
return self;
}
四、SQLite 及FMDB
采用SQLite 数据库来存储数据。SQLitte 作为一个中小型数据库,应用iOS中,跟前几种保存方式相比,相对比较复杂一些,常用框架 FMDB,FMDB 使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码,提供了多线程安全的数据库操作方法,有效地防止数据混乱。
打开数据库
通过指定SQLite数据库文件路径来创建FMDatabase对象。
FMDatabase *db = [FMDatabase databaseWithPath:path];
if (![db open]) {
NSLog(@"数据库打开失败!");
}
在FMDB中,除查询以外的所有操作,都称为“更新”,create、drop、insert、update、delete等,使用executeUpdate:方法执行更新
- (BOOL)executeUpdate:(NSString*)sql, ...
- (BOOL)executeUpdateWithFormat:(NSString*)format, ...
- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments
// 示例
[db executeUpdate:@"UPDATE t_student SET age = ? WHERE name = ?;", @20, @"Jack"]
执行查询
- (FMResultSet *)executeQuery:(NSString*)sql, ...
- (FMResultSet *)executeQueryWithFormat:(NSString*)format, ...
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments
// 查询数据
FMResultSet *rs = [db executeQuery:@"SELECT * FROM t_student"];
// 遍历结果集
while ([rs next]) {
NSString *name = [rs stringForColumn:@"name"];
int age = [rs intForColumn:@"age"];
double score = [rs doubleForColumn:@"score"];
}
FMDatabaseQueue的创建
FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:path];
简单使用
[queue inDatabase:^(FMDatabase *db) {
[db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jack"];
[db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Rose"];
[db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jim"];
FMResultSet *rs = [db executeQuery:@"select * from t_student"];
while ([rs next]) {
// …
}
}];
使用事务
[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
[db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jack"];
[db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Rose"];
[db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jim"];
FMResultSet *rs = [db executeQuery:@"select * from t_student"];
while ([rs next]) {
// …
}
}];
事务回滚
rollback = YES;
鸣谢:智障小鲁班