在iOS学习过程中,有时候需要保持用户数据,比如登录信息、用户的设置选项等,这时候就需要学习数据持久化操作,本节主要学习iOS数据持久化相关的知识。
数据持久化的方式有四种:
1).写入plist文件(属性列表)
2).偏好设置
3).归档(NSKeyedArchiver)
4).NSData
下面分别举例说明四种方式的适用场合以及用法。
1. 写入plist文件(属性列表)
1.1 plist可以存储哪些数据
属性列表是一种XML格式的文件,拓展名为plist
如果对象是NSString、NSDictionary、NSArray、NSData、NSNumber等类型,就可以使用writeToFile:atomically:方法直接将对象写到属性列表文件中。
由于plist文件的root只有Array和Dictionary两种类型,所以最好只保持它们对应数据类型的数据。
比如当你存储字符串类型的数据的时候,Type就为空了。
1.2 如何存储
#pragma mark - 存储数据
- (IBAction)btnSaveData_Click:(UIButton *)sender
{
NSString *str = @"hello";
NSString *filePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0] stringByAppendingPathComponent:@"test_str.plist"];
BOOL result = [str writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
if (result)
{
NSLog(@"存储数据成功");
}
else
{
NSLog(@"存储数据失败!");
}
}
自动生成的文件:
注意:plist不能存储自定义对象类型!
<span style="color:#000000;">#pragma mark - 存储数据
- (IBAction)btnSaveData_Click:(UIButton *)sender
{
// 文件的沙河路径
NSString *filePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0] stringByAppendingPathComponent:@"test_obj.plist"];
// 创建Student对象
CYStudent *stu = [[CYStudent alloc]init];
stu.name = @"zhangsan";
stu.age = 18;
NSArray *arrTmp = @[stu];
BOOL result = [arrTmp writeToFile:filePath atomically:YES];
if (result)
{
NSLog(@"存储数据成功");
}
else
{
NSLog(@"存储数据失败!");
}
}</span>
程序运行结果如下:
1.3 plist文件的存储与读取过程
2. 偏好设置
2.1 使用场景
很多iOS应用都支持偏好设置,比如保存用户名、密码、字体大小等设置,iOS提供了一套标准的解决方案来为应用加入偏好设置功能
每个应用都有个NSUserDefaults实例,通过它来存取偏好设置。比如,保存用户名、字体大小、是否自动登录。
2.2 如何使用
登录成功后保存数据:
[[NSUserDefaults standardUserDefaults]setObject:self.txtAccount.text forKey:@"account"];
[[NSUserDefaults standardUserDefaults]setObject:self.txtPWD.text forKey:@"pwd"];
[[NSUserDefaults standardUserDefaults]setBool:self.swchRememberPWD.on forKey:@"isRememberPWD"];
[[NSUserDefaults standardUserDefaults]setBool:self.swchAutoLogin.on forKey:@"isAutoLogin"]; self.txtAccount.text = [[NSUserDefaults standardUserDefaults]objectForKey:@"account"];
self.swchAutoLogin.on = [[NSUserDefaults standardUserDefaults]boolForKey:@"isAutoLogin"];
self.swchRememberPWD.on = [[NSUserDefaults standardUserDefaults]boolForKey:@"isRememberPWD"];
self.txtPWD.text = [[NSUserDefaults standardUserDefaults]objectForKey:@"pwd"]; [defaults synchornize];
@interface CYContact : NSObject /** 姓名 */ @property (nonatomic,copy) NSString *name; /** 电话 */ @property (nonatomic,copy) NSString *phone; @end
#pragma mark - NSCoding协议方法
/*
Encodes the receiverusing a given archiver
通过一个给定的archiver把消息接收者进行编码。
当接收到encodeObject消息的时候,类终端encodeWithCoder方法被调用。
*/
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:_name forKey:CYNameKey];
[aCoder encodeObject:_phone forKey:CYPhoneKey];
}
/*
Returns an objectinitialized from data in a given unarchiver. (required)
从一个给定unarchiver的数据中返回一个初始化对象。
*/
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super init])
{
_name = [aDecoder decodeObjectForKey:CYNameKey];
_phone = [aDecoder decodeObjectForKey:CYPhoneKey];
}
return self;
}
/*
Returnsa new instance that’s a copy of the receiver
返回消息接收者的一个复制的新实例。
*/
- (id)copyWithZone:(NSZone *)zone
{
CYContact *copy = [[[self class] allocWithZone:zone] init];
copy.name = [self.name copyWithZone:zone];
copy.phone = self.phone;
return copy;
}
[NSKeyedArchiver archiveRootObject:self.contacts toFile:CYFilePath];
self.contacts = [NSKeyedUnarchiver unarchiveObjectWithFile:CYFilePath];
4. NSData
4.1 使用场合
使用archiveRootObject:toFile:方法可以将一个对象直接写入到一个文件中,但有时候可能想将多个对象写入到同一个文件中,那么 就要使用NSData来进行归档对象
NSData可以为一些数据提供临时存储空间,以便随后写入文件,或者存放从磁盘读取的文件内容。可以使用[NSMutableData data]创建 可变数据空间
注:黑色箭头表示将对象归档到文件中,红色箭头表示从文件中恢复对象
4.2 如何使用
#pragma mark - 存储数据
- (IBAction)btnSaveData_Click:(UIButton *)sender
{
// NSData-归档2个Person对象到同一文件中
// 实例化对象
CYStudent *stu1 = [CYStudent studentWithName:@"zhangsan" age:18];
CYStudent *stu2 = [CYStudent studentWithName:@"lisi" age:20];
// 新建一块可变数据区
NSMutableData *data = [NSMutableData data];
// 将数据区连接到一个NSKeyedArchiver对象
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
// 开始存档对象,存档的数据都会存储到NSMutableData中
[archiver encodeObject:stu1 forKey:@"stu1"];
[archiver encodeObject:stu2 forKey:@"stu2"];
// 存档完毕(一定要调用这个方法)
[archiver finishEncoding];
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0] stringByAppendingPathComponent:@"datas.data"];
// 将存档的数据写入文件
BOOL result = [data writeToFile:path atomically:YES];
if (result)
{
NSLog(@"存储数据成功");
}
else
{
NSLog(@"存储数据失败!");
}
}
#pragma mark - 读取数据
- (IBAction)btnReadData_Click:(UIButton *)sender
{
// NSData-从同一文件中恢复2个Person对象
// 从文件中读取数据
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0] stringByAppendingPathComponent:@"datas.data"];
NSData *data = [NSData dataWithContentsOfFile:path];
// 根据数据,解析成一个NSKeyedUnarchiver对象
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
CYStudent *stu1 = [unarchiver decodeObjectForKey:@"stu1"];
CYStudent *stu2 = [unarchiver decodeObjectForKey:@"stu2"];
// 恢复完毕
[unarchiver finishDecoding];
NSLog(@"%@",stu1);
NSLog(@"%@",stu2);
}
#pragma mark - 利用归档实现深复制
- (IBAction)btnDeepCopy_Click:(UIButton *)sender
{
// 比如对一个CYStudent对象进行深复制
// 临时存储stu1的数据
CYStudent *stu1 = [CYStudent studentWithName:@"zhangsan" age:18];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:stu1];
// 解析data,生成一个新的Person对象
CYStudent *stu2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
// 分别打印内存地址
NSLog(@"stu1:%p", stu1); // stu1:0x7bdb32b0
NSLog(@"stu2:%p", stu2); // stu2:0x7bdb6b80
}
原文地址:http://blog.csdn.net/chenyblog/article/details/42438029