数据持久化-偏好设置和归档

偏好设置

  • 很多iOS应用都支持偏好设置,比如保存用户名,密码,字体大小等设置,iOS提供了一套标准的解决方案来为应用加入偏好设置功能。
  • 每个应用都有个NSUserDefaults实例,通过他来存取偏好设置
  • 比如,保存用户名,字体大小,是否自动登录
NSUserDefaults *userdefaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:@"shangsan" forKey:@"username"];
[defaults setFloat:18.0f forKey:@"text_size"];
[defaults setBool:YES forKey:@"auto_login"];
// 注意:UserDefaults设置数据时,不是立即写入,而是根据时间戳定时地把缓存中的数据写入本地磁盘。所以调用了set方法之后数据有可能还没有写入磁盘应用程序就终止了。出现以上问题,可以通过调用synchornize方法强制写入
[defaults synchronize];

//读取上次保存的设置
NSString *usernane = [defaults stringForKey:@"username"];
    float textSize = [defaults floatForKey:@"text_size"];
    BOOL autoLogin = [defaults boolForKey:@"auto_login"];

归档NSKeyedArchiver

如果对象是NSString、NSDictionary、NSArray、NSData、NSNumber等类型,可以直接用NSKeyedArchiver进行归档和恢复
不是所有的对象都可以直接用这种方法进行归档,只有遵守了NSCoding协议的对象才可以
NSCoding协议有2个方法:
encodeWithCoder:
每次归档对象时,都会调用这个方法。一般在这个方法里面指定如何归档对象中的每个实例变量,可以使用encodeObject:forKey:方法归档实例变量
initWithCoder:
每次从文件中恢复(解码)对象时,都会调用这个方法。一般在这个方法里面指定如何解码文件中的数据为对象的实例变量,可以使用decodeObject:forKey方法解码实例变量

NSKeyedArchiver-归档Person对象(Person.h)

@interface Person : NSObject<NSCoding> 
@property (nonatomic, copy) NSString *name; 
@property (nonatomic, assign) int age; 
@property (nonatomic, assign) float height; 
@end 

@implementation Person 
- (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; 
} 
@end 

归档(编码) 
Person *person = [[[Person alloc] init]; 
person.name = @"MJ"; 
person.age = 27; 
person.height = 1.83f; 
[NSKeyedArchiver archiveRootObject:person toFile:path]; 

恢复(解码) 
Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:path]; 
NSLog(@"%@%d%.2f",person.name,person.age,person.height);

NSKeyedArchiver-归档对象的注意 :

如果父类也遵守了NSCoding协议,请注意应该在encodeWithCoder:方法中加上一句

[super encodeWithCode:encode];

确保继承的实例变量也能被编码,即也能被归档 ,应该在initWithCoder:方法中加上一句

self = [super initWithCoder:decoder];

确保继承的实例变量也能被解码,即也能被恢复

NSData归档

  • 使用archiveRootObject: toFile:方法可以将一个对象直接写入到一个文件中,但有时候可能将多个对象写入到同一个文件中,那么就要使用NSData来进行归档对象
  • NSData可以为一些数据提供临时储存空间,以便随后写入文件,或者存放从磁盘读取的文件内容,可以使用[NSMutableData data]创建可变数据空间

NSData-归档2个Person对象到同一文件中

归档(编码) 

// 新建一块可变数据区 
NSMutableData *data = [NSMutableData data]; 
// 将数据区连接到一个NSKeyedArchiver对象 
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; 

// 开始存档对象,存档的数据都会存储到NSMutableData中 
[archiver encodeObject:person1 forKey:@"person1"]; 
[archiver encodeObject:person2 forKey:@"person2"]; 
// 存档完毕(一定要调用这个方法) 
[archiver finishEncoding]; 
// 将存档的数据写入文件 
[data writeToFile:path atomically:YES]; 

NSData-从同一文件中恢复2个Person对象

恢复(解码) 
// 从文件中读取数据 
NSData *data = [NSData dataWithContentsOfFile:path]; 
// 根据数据,解析成一个NSKeyedUnarchiver对象 
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; 
Person *person1 = [unarchiver decodeObjectForKey:@"person1"]; 
Person *person2 = [unarchiver decodeObjectForKey:@"person2"]; 
// 恢复完毕 
[unarchiver finishDecoding]; 

利用归档实现深复制

比如对一个Person对象进行深复制

//临时存储personl的数据
 NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person];

//解析data,生成一个新的Person对象
 Person *person2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值