前面已经讲解了SQLite,FMDB以及CoreData的基本操作和代码讲解(CoreData也在不断学习中,上篇博客也会不断更新中)。本篇我们将讲述在实际开发中,所使用的iOS数据持久化的方式以及怎么会使用到这些方式,都会以本人实际开发的场景为例,大约需要花10-15分钟,欢迎大家指正。

一、前言

和大家说一个真实故事,前年我去美图面试(当时的技术仅仅是UI和接口的实现,并不注重很多底层实现和很多概念的原理,换句话说,就是真正的码农),过了技术第一轮和第二轮(前两年的也就是问问技术点的实现),到了第三轮的时候,应该是项目经理面试我,其中一个题目问住了我,因为iOS我是自学的,也算是不断摸索的。

“请你说一下iOS 一般会默认自己程序的目录,请说一下这个目录机构,以及组成部分,里面包含什么?”

当时的情景就是,我是谁,我在哪,大家也可以想一下!!!

其实那个项目经理问的就是我们经常听到的沙盒文件,其中iOS在程序默认下只会访问自己的程序目录-也就是沙盒文件。

1. 寻找沙盒文件位置

大家可能不知道怎么查看正在真机(或者模拟器)运行下的沙盒文件,可以按照下面的步骤查看

1.1 第一步,打开项目,选择windows(我是以真机为例,模拟器亦是)

1.2 第二步,进入界面,选择自己的app,点击绿色按钮,

1.3 第三步,选择第二个Download Container,导出到指定的文件夹(我是导出到桌面)

1.4 最后,我们发现桌面有个后缀名为.xcappdata的文件夹,我是导入到桌面。

2.沙盒文件目录结构

2.1  在1.4中后缀.xcappdata,右击选择->显示包内容,打开看到目录如下图,也可以继续点击查看更详细内容。

2.2目录讲解

:->AppData:也就是应用程序包,存的是程序的源文件,其中里面有可执行的文件以及资源文件。通过以下可以获得路径

  1. NSString *path = [[NSBundle mainBundle] bundlePath];
  2. NSLog(@"%@", path);

AppData里面包括了以下内容:

(1)Documents

也是我们经常使用到的目录,我们经常看到iTunes同步,同步的就是此文件中的内容,Documents适合存比较重要的数据。我们可以通过以下代码拿到Documents

  1. NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
  2. NSLog(@"%@", path);

(2)Library

Library比较适合存储比较大的数据,并且iTunes不会同步此文件,也不会备份。可以通过以下拿到路径

  1. NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
  2. NSLog(@"%@", path);

(2.1)获取Caches目录路径

  1. NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
  2. NSLog(@"Caches目录路径是%@",docDir);

(2.2)Preferences

主要包括了程序中的偏好设置文件,下面会讲述这个Preferences

(3)SystemData

目前暂不讲解这个目录(里面目录为空)

(4)tmp

用于存储临时文件,主要保存程序再次启动中不需要的信息数据,并且该路径中的文件并不会被itunes同步和备份。通过以下获得

  1. NSString *tmpDir = NSTemporaryDirectory();

上面就是前言部分,大家这篇博客,我们主要讲述iOS数据持久化操作,好,我们正式以项目的形式讲述iOS的数据持久化操作。

二、iOS数据持久化操作

对于iOS的数据持久化操作,在网上也是有很多讲解,本篇主要讲述本人项目中使用到的方式进行讲解。iOS持久化操作方式主要有以下五种方式:

1. plist文件方式,也就是属性列表

2. preference 也就是偏好设置

3. NSKeyedArchiver 也就是归档

4. SQLite

5. CoreData

下面我们就一一讲解五种方式,以项目为例。

2.1 plist (属性列表)

plist是将比较特定的类(不经常改变的类),通过XML的方式存储在目录中。

自己项目有个分享的功能,因为分享渠道是固定的以及界面内容不会改变,所以自己当初采取plist文件的方式进行存储。效果如下:

具体分享平台自己使用plist文件进行存储,下面是自己plist文件

点开plist文件,如下图

右击该plist文件->选择Open As ->选择Source Code,如下

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3. <plist version="1.0">
  4. <dict>
  5. <key>data</key>
  6. <array>
  7. <dict>
  8. <key>titleLabel</key>
  9. <string>微信好友</string>
  10. <key>imageView</key>
  11. <string>cart_wx</string>
  12. </dict>
  13. <dict>
  14. <key>titleLabel</key>
  15. <string>朋友圈</string>
  16. <key>imageView</key>
  17. <string>cart_friend</string>
  18. </dict>
  19. <dict>
  20. <key>titleLabel</key>
  21. <string>QQ好友</string>
  22. <key>imageView</key>
  23. <string>cart_qq</string>
  24. </dict>
  25. <dict>
  26. <key>titleLabel</key>
  27. <string>QQ空间</string>
  28. <key>imageView</key>
  29. <string>cart_que</string>
  30. </dict>
  31. </array>
  32. </dict>
  33. </plist>

下面讲述怎么使用分享plist文件。

通过上图和XML文件可以看出最外面是字典,我在项目是使用懒加载方式加载这个字典

代码如下:

  1. - (NSDictionary *)configDatas{
  2. if (!_configDatas) {
  3. NSString *path = [[NSBundle mainBundle]pathForResource:@"IOACartShareDatas" ofType:@".plist"];
  4. NSDictionary *dic = [NSDictionary dictionaryWithContentsOfFile:path];
  5. _configDatas = dic;
  6. }
  7. return _configDatas;
  8. }

在分享的view内进行传值

然后进入shareView中查看具体赋值,布局采用了UICollectionView布局

补充一下:

自己上面是一个一个在plist里面创建的元素,也可以通过writeToFile存储以及arrayWithContentsOfFile取文件。

(1)writeToFile存储方式

  1. NSArray *array = @[@"2", @"1", @"3"];
  2. [array writeToFile:fileName atomically:YES];

(2)arrayWithContentsOfFile读取方式

  1. NSArray *result = [NSArray arrayWithContentsOfFile:fileName];
  2. NSLog(@"%@", result);

2.2 Preference偏好设置

Preference偏好设置一般用存储应用程序的配置信息文件,最好不要在Preference中存储其他数据,Preference通过操作NSUserDefaults完成操作。

2.2.1 获得NSUserDefaults文件

  1. //获得NSUserDefaults文件
  2. NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

2.2.2 开始向文件中写入内容

  1. [userDefaults setObject:@"哈哈哈" forKey:@"a"];
  2. [userDefaults setBool:YES forKey:@"success"];
  3. [userDefaults setInteger: forKey:@"age"];

2.2.3 确定是否同步。确定是否调用synchronize方法,想要写入文件时,就应该调用[userDefaults synchronize]方法

如果同步

  1. [userDefaults synchronize];

反之,不写。

2.2.4 在合适的地方调取文件

  1. NSString *name = [userDefaults objectForKey:@"a"];
  2. BOOL sex = [userDefaults boolForKey:@"success"];
  3. NSInteger age = [userDefaults integerForKey:@"age"];
  4. NSLog(@"%@, %d, %ld", name, sex, age);

Preference会把所有的数据存储到一个文件中,也就是在上面preference文件下的plist文件。

2.3 NSKeyedArchiver 归档

在使用归档NSKeyedArchiver一定要遵守NSCoding协议,也就是遵守了NSCoding协议的对象,我们都可以通过归档NSKeyedArchiver进行序列化。

通过查看NSCoding协议文件,发现如下

NSCoding协议文件声明了两个文件,上述图中,也是必须要实现的。encodeWithCoder用于将对象编码到归档中,而initWithCoder用于通过解档来获取一个新对象。

需要注意的是:

假如要归档的类恰好是一个自定义类的子类时候,就应该要在归档和解档之前要首先实现父类的方法,也就是必须要实现以下两个方法:[super encodeWithCoder:aCoder]和[super initWithCoder:aDecoder]

拓展->

NSCopying协议文件如下(有一次面试官问我,NSCopying与NSMutableCopying),大家当增长一个知识点吧!

下面以自己以前的项目为准,讲述归档的使用(因为以前项目较小,又是独立开发,采用NSKeyedArchiver存储信息)。

2.3.1 使用NSKeyedArchiver归档存储用户登录部分信息,注销登录清除。定义了一个类AppUserDefaults

点开AppUserDefaults.h文件定义登录获取的属性(仅仅展示部分属性,实现都一样)

通过以下方法对登录信息的赋值

我们看一下归档和解档,以及上面方法的实现(注解上面type属性是代表是不同短登录:例如医生端和患者端)

2.3.2 encodeWithCoder归档(显示部分属性,否则界面太大)

2.3.2 initWithCoder解档

2.3.2 登录通过setSessionWithLoginName设置属性

  1. + (void)setSessionWithLoginName:(NSString *)loginName
  2. version:(NSString *)version
  3. loginTime:(long long)loginTime
  4. id_:(long)id_
  5. userType:(int)userType
  6. name:(NSString *)name
  7. phone:(NSString *)phone
  8. pic:(NSString *)pic
  9. companyName:(NSString *)companyName
  10. address:(NSString *)address
  11. type:(NSInteger)type
  12. cityName:(NSString *)cityName
  13. cityId:(long)cityId
  14. latitude:(NSString *)latitude
  15. longitude:(NSString *)longitude {
  16. //判断版本号,通过session
  17. AppUserDefaults *session = [AppUserDefaults getSession];
  18. if (session && ![session.version isEqualToString:@""]) {
  19. if (type != -)
  20. session.type = type;
  21. if (loginTime != -)
  22. session.loginTime = loginTime;
  23. if ([loginName isNotBlank])
  24. session.loginName = loginName;
  25. if ([version isNotBlank])
  26. session.version = version;
  27. if (id_ != -)
  28. session.id_ = id_;
  29. }
  30. NSData *data = [NSKeyedArchiver archivedDataWithRootObject:session];
  31. if (data) {
  32. NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
  33. [user setObject:data forKey:@"session"];
  34. [user synchronize];
  35. }
  36. }
  37.  
  38. + (AppUserDefaults *)getSession {
  39. AppUserDefaults *session = nil;
  40. NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
  41. NSData *data = [user objectForKey:@"session"];
  42. if (data) {
  43. session = [NSKeyedUnarchiver unarchiveObjectWithData:data];
  44. if (session && [session.version isEqualToString:@""]) {
  45. session = nil;
  46. }
  47. }
  48. return session;
  49. }

2.3.4 上面就是AppUserDefaults文件内容,下面讲述在登录时候进行赋值。

首先要懒加载AppUserDefaults

  1. - (AppUserDefaults *)userDefaults{
  2. if (_userDefaults == nil) {
  3. _userDefaults = [AppUserDefaults getSession];
  4. }
  5. return _userDefaults;
  6. }

登录成功时赋值

2.3.5 如果用户注销之后或者退出应用应该给重新清空,如下:

总结:

使用NSKeyedArchiver的工厂方法[NSKeyedArchiver archiveRootObject:obj toFile:path];方法。demo如下:

  1. NSString *file = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"student.data"];
  2. Person *person = [[Person alloc] init];
  3. person.avatar = self.avatarView.image;
  4. person.name = self.nameField.text;
  5. person.age = [self.ageField.text integerValue];
  6. [NSKeyedArchiver archiveRootObject:person toFile:file];

如果想解档需要调用[NSKeyedUnarchiver unarchiveObjectWithFile:path];方法如下

  1. NSString *file = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"student.data"];
  2. Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:file];
  3. if (person) {
  4. self.avatarView.image = person.avatar;
  5. self.nameField.text = person.name;
  6. self.ageField.text = [NSString stringWithFormat:@"%ld", person.age];
  7. }

在这之前还是要定义属性和实现协议方法

  1. //1.遵循NSCoding协议
  2. @interface student : NSObject //2.设置属性
  3. @property (strong, nonatomic) UIImage *avatar;
  4. @property (copy, nonatomic) NSString *name;
  5. @property (assign, nonatomic) NSInteger age;
  6. @end
  1. //解档
  2. - (id)initWithCoder:(NSCoder *)aDecoder {
  3. if ([super init]) {
  4. self.avatar = [aDecoder decodeObjectForKey:@"avatar"];
  5. self.name = [aDecoder decodeObjectForKey:@"name"];
  6. self.age = [aDecoder decodeIntegerForKey:@"age"];
  7. }
  8. return self;
  9. }
  10. //归档
  11. - (void)encodeWithCoder:(NSCoder *)aCoder {
  12. [aCoder encodeObject:self.avatar forKey:@"avatar"];
  13. [aCoder encodeObject:self.name forKey:@"name"];
  14. [aCoder encodeInteger:self.age forKey:@"age"];
  15. }

2.4 SQLite

以下并不是推广博客,主要是很多内容,没有必要写第二遍,即使写,也没用专门一篇详细。

关于SQLite讲解,请查看以前博客https://www.cnblogs.com/guohai-stronger/p/9218175.html

SQLite的使用还是很麻烦的,在一般的项目开发中,会使用FMDB操作,这个也有讲解,https://www.cnblogs.com/guohai-stronger/p/9246653.html

对于SQLite和FMDB的使用区别,看这篇博客希望对大家有所帮助 https://www.cnblogs.com/guohai-stronger/p/9251131.html

2.5 CoreData

CoreData目前自己所从事的工作还没有使用过CoreData,但自己通过尝试demo,还是有所感悟,关于CoreData的理解,自己也写了一个博客,https://www.cnblogs.com/guohai-stronger/p/9254293.html

以上就是iOS数据存储的5中方式,都是自己真实项目所使用的,希望对大家有所帮助 !!!如有错误的地方请告诉我,大家共同进步。

iOS -数据持久化方式-以真实项目讲解的更多相关文章

  1. iOS数据持久化方式及class_copyIvarList与class_copyPropertyList的区别

    iOS数据持久化方式:plist文件(属性列表)preference(偏好设置)NSKeyedArchiver(归档)SQLite3CoreData沙盒:iOS程序默认情况下只能访问自己的程序目录,这 ...

  2. iOS开发中的4种数据持久化方式【二、数据库 SQLite3、Core Data 的运用】

                   在上文,我们介绍了ios开发中的其中2种数据持久化方式:属性列表.归档解档.本节将继续介绍另外2种iOS持久化数据的方法:数据库 SQLite3.Core Data 的运 ...

  3. iOS中的数据持久化方式

    iOS中的数据持久化方式,基本上有以下四种:属性列表.对象归档.SQLite3和Core Data. 1.属性列表 涉及到的主要类:NSUserDefaults,一般 [NSUserDefaults ...

  4. iOS 数据持久化(扩展知识:模糊背景效果和密码保护功能)

    本篇随笔除了介绍 iOS 数据持久化知识之外,还贯穿了以下内容: (1)自定义 TableView,结合 block 从 ViewController 中分离出 View,轻 ViewControll ...

  5. 四种数据持久化方式(下) :SQLite3 和 Core Data

    在上文,我们介绍了iOS开发中的其中2种数据持久化方式:属性列表.归档解档. 本节将继续介绍另外2种iOS持久化数据的方法:数据库 SQLite3.Core Data 的运用: 在本节,将通过对4个文 ...

  6. iOS开发笔记-swift实现iOS数据持久化之归档NSKeyedArchiver

    IOS数据持久化的方式分为三种: 属性列表 (plist.NSUserDefaults) 归档 (NSKeyedArchiver) 数据库 (SQLite.Core Data.第三方类库等 归档(又名 ...

  7. IOS数据持久化之归档NSKeyedArchiver

    IOS数据持久化的方式分为三种: 属性列表 (自定义的Property List .NSUserDefaults) 归档 (NSKeyedArchiver) 数据库 (SQLite.Core Data ...

  8. iOS开发中的4种数据持久化方式【一、属性列表与归档解档】

    iOS中的永久存储,也就是在关机重新启动设备,或者关闭应用时,不会丢失数据.在实际开发应用时,往往需要持久存储数据的,这样用户才能在对应用进行操作后,再次启动能看到自己更改的结果与痕迹.ios开发中, ...

  9. iOS数据持久化-OC

    沙盒详解 1.IOS沙盒机制 IOS应用程序只能在为该改程序创建的文件系统中读取文件,不可以去其它地方访问,此区域被成为沙盒,所以所有的非代码文件都要保存在此,例如图像,图标,声音,映像,属性列表,文 ...

随机推荐

  1. Apache启动不成功时,用命令行检测(新手)

    1,在配置Apache服务器时,经常要在httpd.conf 修改和添加一些代码,编写中,误写或者写错时,无法正常启动时,直接报错The requested operation has failed! ...

  2. 【repost】javascript callback

    在javascript中回调函数非常重要,它们几乎无处不在.像其他更加传统的编程语言都有回调函数概念,但是非常奇怪的是,完完整整谈论回调函数的在线教程比较少,倒是有一堆关于call()和apply() ...

  3. [转] List of OpenFlow Software Projects

    List of OpenFlow Software Projects (that I know of) http://yuba.stanford.edu/~casado/of-sw.html (I a ...

  4. Spring-Data-Jpa环境配置与实际应用

    上次我们讲述了<Spring-Data-Jpa概述与接口>,接下来我们再讲讲Spring-Data-Jpa环境配置与实际应用. Spring-Data 方法定义规范与使用配置 简单条件查询 ...

  5. 8.快速索引、listview

    实现这样的效果 布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" ...

  6. Hexo博客主题优化

    Hexo博客主题优化 添加背景图 在 themes/*/source/css/_custom/custom.styl 中添加如下代码: body{ background:url(/images/bg. ...

  7. 《http权威指南》读书笔记8

    概述 最近对http很感兴趣,于是开始看<http权威指南>.别人都说这本书有点老了,而且内容太多.我个人觉得这本书写的太好了,非常长知识,让你知道关于http的很多概念,不仅告诉你怎么做 ...

  8. puppetdb搭建

    puppetdb搭建 在agent端跑puppet agent -t 正常的情况下,安装puppetdb 部署postgresql数据库 部署puppetdb 建立puppetserver与puppe ...

  9. [Postman]发出SOAP请求(18)

    使用Postman发出SOAP请求: 将SOAP端点作为URL.如果您使用的是WSDL,那么请将WSDL的路径作为URL. 将请求方法设置为POST. 打开原始编辑器,并将正文类型设置为“text / ...

  10. java 常见面试题总结(一)

    1.Redis应用场景 答:分布式会话,分布式锁,计数器,缓存,消息队列,排行榜,最新列表. 2.如何访问一个类的私有方法? 答:使用反射进行访问,代码如下: package cn.entity; p ...