iOS学习笔记
发表时间:2020-10-19
发布人:葵宇科技
浏览次数:38
在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两种类型,所以最好只保持它们对应数据类型的数据。
[img]http://img.blog.csdn.net/20150106121855385?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hlbnlibG9n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
比如当你存储字符串类型的数据的时刻,Type就为空了。
[img]http://img.blog.csdn.net/20150106121934375?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hlbnlibG9n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
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(@"存储数据掉败!"); } }
法度榜样运行结不雅如下:
[img]http://img.blog.csdn.net/20150106122018484?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hlbnlibG9n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
主动生成的文件:
[img]http://img.blog.csdn.net/20150106122114225?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hlbnlibG9n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
留意: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>法度榜样运行结不雅如下:
[img]http://img.blog.csdn.net/20150106122201493?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hlbnlibG9n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
1.3 plist文件的存储与攫取过程
[img]http://img.blog.csdn.net/20150106122241289?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hlbnlibG9n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
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"];
留意:UserDefaults设置数据时,不是急速写入,而是根据时光戳准时地把缓存中的数据写入本地磁盘。所声调用了set办法之后数据有可能还没有写入磁盘应用法度榜样就终止了。出现以上问题,可以经由过程调用synchornize办法强迫写入
[defaults synchornize];
3. 归档(NSKeyedArchiver)
3.1 应用处合
如不雅对象是NSString、NSDictionary、NSArray、NSData、NSNumber等类型,可以直接用NSKeyedArchiver进行归档和恢复
不是所有的对象都可以直接用这种办法进行归档,只有遵守了NSCoding协定的对象才可以
NSCoding协定有2个办法:
1)encodeWithCoder:
每次归档对象时,都邑调用这个办法。一般在这个办法琅绫擎指定若何归档对象中的每个实例变量,可以应用encodeObject:forKey:办法归档实例变量
2)initWithCoder:
每次大年夜文件中恢复(解码)对象时,都邑调用这个办法。一般在这个办法琅绫擎指定若何解码文件中的数据为对象的实例变量,可以应用decodeObject:forKey办法解码实例变量
3.2 若何应用
1> 自定义实体类
@interface CYContact : NSObject /** 姓名 */ @property (nonatomic,copy) NSString *name; /** 德律风 */ @property (nonatomic,copy) NSString *phone; @end
2> 实现NSCoding协定办法
#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 =
3> 归档
[NSKeyedArchiver archiveRootObject:self.contacts toFile:CYFilePath];
4> 接档
self.contacts = [NSKeyedUnarchiver unarchiveObjectWithFile:CYFilePath];
5> 留意点
如不雅父类也遵守了NSCoding协定,请留意:
? 应当在encodeWithCoder:办法中加上一句[super encodeWithCode:encode];确保持续的实例变量也能被编码,即也能被归档
? 应当在initWithCoder:办法中加上一句self = [super initWithCoder:decoder];确保持续的实例变量也能被解码,即也能被恢复
4. NSData
4.1 应用处合
应用archiveRootObject:toFile:办法可以将一个对象直接写入到一个文件中,但有时刻可能想将多个对象写入到同一个文件中,那么 就要应用NSData来进行归档对象
NSData可认为一些数据供给临时存储空间,以便随后写入文件,或者存放大年夜磁盘攫取的文件内容。可以应用[NSMutableData data]创建 可变数据空间
[img]http://img.blog.csdn.net/20150106122333393?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hlbnlibG9n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
注:黑色箭头表示将对象归档到文件中,红色箭头表示大年夜文件中恢复对象
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 }