偏好设置
- 很多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];