iOS学习笔记-数据持久化

在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"];

注意: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 = [[[self class] allocWithZone:zone] init];
       copy.name = [self.name copyWithZone:zone];
       copy.phone = self.phone;
       return 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]创建  可变数据空间

注:黑色箭头表示将对象归档到文件中,红色箭头表示从文件中恢复对象

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
	}
时间: 2024-08-27 22:41:18

iOS学习笔记-数据持久化的相关文章

ios学习笔记——数据持久化

一.沙盒 沙盒目录是一种数据安全策略,很多系统都采用沙盒设计. 沙盒目录设计的原理就是只能允许自己的应用程序访问目录,而不允许其他的应用访问. 1.Documents目录:该目录用于存储非常大的文件或非常频繁更新的数据,能够进行iTunes或iCloud的备份,获取目录位置的代码如下: 1 NSString * pathArr = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) la

ios开发学习笔记--数据持久化之数据库(SQLite.swift)

数据持久化之SQLite数据库(SQLite.swift使用) 一.     简介 SQLite是一款轻型的嵌入式数据库,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就足够了.它的处理速度比Mysql.PostgreSQL这两款著名的数据库都还快.SQLite提供的是一些C函数接口,你可以用这些函数操作数据库.通过使用这些接口,传递一些标准 sql 语句(以 char * 类型)给 SQLite函数,SQLite就会为你操作数据库 一个数据库中的表就算是一个文件,一般是将这个文件放

ios开发学习笔记--数据持久化之Core Data

数据持久化之CoreDate 一.     Core Data简介 Core Data是苹果公司为了实现数据持久化提供的一个框架,而不是一个数据库,提供对象-关系映射[ORM]的功能(将对象转化为数据,也能将保存在数据库的数据还原为对象). 虽然底层操作与SQLite相似,但是并不直接写SQL语句,而且只能整个取出实体记录,然后分解之后才能得到某个属性. Core Data能存储的类型:SQLite数据库.XML.二进制.自定义数据类型 一般情况下,Core Data的数据存在沙盒下的Docum

iOS 学习笔记——0005(数据存储)

先发一个练手的小demo,自己写的简略通讯录,已上传至github https://github.com/liaoshaolim/addressBook 1.NSKeyedArchiver:(归档) 这里用一个添加联系人的例子来说明: 注意:归档形式保存数据,需要该对象遵守NSCoding协议,而且对应的必须提供encodeWithCoder和initWithCoder方法 因为归档是一次性的,解压也是一次性的,所以小量的ok,如果量大的话,改一个小地方就要归档或解压全部,效率会比较低 //用一

IOS学习:ios中的数据持久化初级(文件、xml、json、sqlite、CoreData)

IOS学习:ios中的数据持久化初级(文件.xml.json.sqlite.CoreData) 分类: ios开发学习2013-05-30 10:03 2316人阅读 评论(2) 收藏 举报 iOSXMLJSONSQLiteCoreData 一.文件操作 1.因为应用是在沙盒(Sandbox)中的,在文件读写权限上受到限制,只能在几个目录下读写文件: * Documents:应用中用户数据可以放在这里,iTunes备份和恢复的时候会包括此目录 * tmp:存放临时文件,iTunes不会备份和恢复

iOS学习笔记之UITableViewController&amp;UITableView

iOS学习笔记之UITableViewController&UITableView 写在前面 上个月末到现在一直都在忙实验室的事情,与导师讨论之后,发现目前在实验室完成的工作还不足以写成毕业论文,因此需要继续思考新的算法.这是一件挺痛苦的事情,特别是在很难找到与自己研究方向相关的文献的时候.也许网格序列水印这个课题本身的研究意义就是有待考证的.尽管如此,还是要努力的思考下去.由于实验室的原因,iOS的学习进度明显受到影响,加之整理文档本身是一件耗费时间和精力的事情,因此才这么久没有写笔记了. M

IOS学习笔记 -- Modal和Quartz2D

一. Modal1.Modal的默认效果:新控制器从屏幕的最底部往上钻,直到盖住之前的控制器为止;Modal只是改变了View的现实,没有改变rootViewController 2.常用方法1>.以Modal的形式展示控制器- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion2>.关

iOS学习笔记(1)— UIView 渲染和内容管理

iOS学习笔记(1)— UIView 渲染和内容管理 iOS中应用程序基本上都是基于MVC模式开发的.UIView就是模型-视图-控制器中的视图,在iOS终端上看到的.摸到的都是UIView. UIView在屏幕上定义了一个矩形区域和管理区域内容的接口.在运行时,一个视图对象控制该区域的渲染:UIView继承自UIResponder,UIResponder是用来响应事件的类,UIView也具有响应事件的能力.所以说UIView具有三个基本的功能,绘制内容并管理内容的布局,响应用户交互,动画.正是

iOS学习笔记-精华整理

iOS学习笔记总结整理 一.内存管理情况 1- autorelease,当用户的代码在持续运行时,自动释放池是不会被销毁的,这段时间内用户可以安全地使用自动释放的对象.当用户的代码运行告一段 落,开始等待用户的操作,自动释放池就会被释放掉(调用dealloc),池中的对象都会收到一个release,有可能会因此被销毁. 2-成员属性:     readonly:不指定readonly,默认合成getter和setter方法.外界毫不关心的成员,则不要设置任何属性,这样封装能增加代码的独立性和安全