1 持久化目的
- 快速展示,提升体验
- 已经加载过的数据,用户下次查看时,不需要再次从网络(磁盘)加载,直接展示给用户
- 节省用户流量(节省服务器资源)
- 对于较大的资源数据进行缓存,下次展示无需下载消耗流量
- 同时降低了服务器的访问次数,节约服务器资源。(图片)
- 离线使用。
- 用户浏览过的数据无需联网,可以再次查看。
- 部分功能使用解除对网络的依赖。(百度离线地图、图书阅读器)
- 无网络时,允许用户进行操作,等到下次联网时同步到服务端。
- 记录用户操作
- 草稿:对于用户需要花费较大成本进行的操作,对用户的每个步骤进行缓存,用户中断操作后,下次用户操作时直接继续上次的操作。
- 已读内容标记缓存,帮助用户识别哪些已读。
- 搜索记录缓存
2 数据持久化方式分类
2.1 内存缓存
- 定义
对于使用频率比较高的数据,从网络或者磁盘加载数据到内存以后,使用后并不马上销毁,下次使用时直接从内存加载。 - 案例
iOS系统图片加载——[UIImage imageNamed:@"imageName"]
网络图片加载三方库:SDWebImage
- 实现
实现内存缓存的技术手段包括苹果官方提供的NSURLCache
,NSCache
,还有性能和API上比较有优势的开源缓存库YYCache
、PINCache
等。
2.2 磁盘缓存
- 定义
将从网络加载的、用户操作产生的数据写入到磁盘,用户下次查看、继续操作时,直接从磁盘加载使用。 - 案例
用户输入内容草稿缓存(如:评论、文本编辑)
网络图片加载三方库:SDWebImage
搜索历史缓存 - 实现
NSUserDefault
适合小规模数据,弱业务相关数据的缓存。keychain
Keychain
是苹果提供的带有可逆加密的存储机制,普遍用在各种存用户名、密码的需求上。另外,Keychain
是系统级存储,还可以被iCloud
同步,即使App
被删除,Keychain
数据依然保留,用户下次安装App
,可以直接读取,通常会用来存储用户唯一标识串。所以需要加密、同步iCloud
的敏感小数据,一般使用Keychain
存取。- 文件存储
Plist
:一般结构化的数据可以Plist
的方式去持久化archive
:Archive
方式可以存取遵循协议的数据,比较方便的是存取使用的都是对象,不过中间的序列化和反序列化需要花费一定的性能,可以在想要使用对象直接进行磁盘存取时使用。Stream
:指文件存储,一般用来存图片、视频文件等数据
- 数据库存储
数据库适合存取一些关系型的数据;可以在有大量的条件查询排序类需求时使用。Core Data
:苹果官方封装的ORM(Object Relational Mapping)
FMDB
:github
最受欢迎的iOS sqlite
封装开源库之一WCDB
:微信团队在自己使用的sqlite封装基础上的开源实现,具有ORM(Object Relational Mapping)
的特性,支持iOS
、Android
。Realm
:由Y Combinator
孵化的创业团队开源出来的一款跨平台(iOS
、Android
)移动数据库。
2.3 应该用哪种缓存方案
根据需求选择:
- 简单数据存储直接写文件、key-value存取即可。
- 需要按照一些条件查找、排序等需求的,可以使用sqlite等关系型存储方式。
- 不希望App删除后清除的小容量数据(用户名、密码、token)存keychain。
3 沙盒机制介绍
iOS
中的沙盒机制是一种安全体系。为了保证系统安全,iOS
每个应用程序在安装时,会创建属于自己的沙盒文件(存储空间)。应用程序只能访问自身的沙盒文件,不能访问其他应用程序的沙盒文件,当应用程序需要向外部请求或接收数据时,都需要经过权限认证,否则,无法获取到数据。所有的非代码文件都要保存在此,例如属性文件plist
、文本文件、图像、图标、媒体资源等。
3.1 沙盒机制与持久化的关系
iOS 中的持久化是指将数据在应用程序退出后仍然保留在存储设备上的能力。而沙盒机制是 iOS 系统为每个应用程序提供的安全性措施,通过将每个应用程序限制在自己的沙盒中,确保应用程序只能访问自己的数据,并不能访问其他应用程序的数据。
持久化和沙盒机制在 iOS
应用程序中是密切相关的,因为应用程序需要在沙盒中对数据进行持久化。iOS
提供了几种方式来实现数据持久化,而所有这些方式都是在应用程序的沙盒内进行的。以下是 iOS
持久化与沙盒机制的关系:
- 文件储存持久化: 在
iOS
应用程序中,可以使用文件系统来持久化数据,例如将数据保存到文件中。iOS
应用程序只能在自己的沙盒目录中创建、读取和写入文件,不能访问其他应用程序的文件。常见的文件系统持久化方式包括使用NSFileManager
类进行文件操作,或者使用NSData
或NSString
类的方法将数据写入文件。 UserDefaults
持久化:NSUserDefaults
是一种简单的持久化方式,可以用于保存用户的偏好设置、配置信息等。虽然数据是持久化的,但是它们仍然存储在应用程序的沙盒中,并且只能被当前应用程序访问。- 数据库持久化:它将数据保存到
SQLite
数据库中或其他数据存储。这些也是在应用程序的沙盒内进行数据持久化的方式。 Keychain
持久化:Keychain
是iOS
提供的一种安全存储敏感数据的方式,例如密码、密钥等。Keychain
中的数据也是在应用程序的沙盒内进行持久化,并且具有更高的安全性保护,确保只有应用程序本身才能访问这些数据。
总的来说,iOS
中的持久化操作都是在应用程序的沙盒内进行的,受到沙盒机制的限制,确保应用程序只能访问自己的数据,保证了应用程序之间的数据隔离和安全性。
3.2 沙盒的目录结构
3.2.1 获取应用程序的沙盒路径:
// 获取沙盒根目录路径
NSString *path = NSHomeDirectory();
注意: 每次编译代码会生成新的沙盒路径,注意是编译不是启动,所以模拟机或者真机运行,每次运行所得到的沙盒路径都是不一样的,线上版本app真机不会生成新的沙盒路径。
上面的代码得到的就是当前应用程序目录的路径,该目录下就是应用程序的沙盒,在该目录下有4个文件夹:Documents
、Library
、SystemData
、tmp
,当前应用程序只能访问该目录下的文件。
3.2.2 访问沙盒目录常用C函数介绍
//文件路径搜索
FOUNDATION_EXPORT NSArray<NSString *> *NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask, BOOL expandTilde);
该方法返回值为一个数组,在iphone中由于只有一个唯一路径,所以直接取数组第一个元素即可。
该函数的作用是返回指定搜索目录下的路径数组。它接受三个参数:
directory
:NSSearchPathDirectory
类型的枚举值,用于指定搜索的目录。常见的枚举值包括:
//常用的NSSearchPathDirectory枚举值
typedef NS_ENUM(NSUInteger, NSSearchPathDirectory) {
NSApplicationDirectory = 1, // supported applications (Applications)
NSDemoApplicationDirectory, // unsupported applications, demonstration versions (Demos)
NSAdminApplicationDirectory, // system and network administration applications (Administration)
NSLibraryDirectory, // various documentation, support, and configuration files, resources (Library)
NSUserDirectory, // user home directories (Users)
NSDocumentationDirectory, // Library 下的(Documentation)模拟器上没有创建
NSDocumentDirectory, // documents (Documents)
};
domainMask
:NSSearchPathDomainMask
类型的位掩码,用于指定搜索路径的范围。常见的枚举值包括:
typedef NS_OPTIONS(NSUInteger, NSSearchPathDomainMask) {
NSUserDomainMask = 1, // 用户目录 - 基本上就用这个。
NSLocalDomainMask = 2, // 本地
NSNetworkDomainMask = 4, // 网络
NSSystemDomainMask = 8, // 系统
NSAllDomainsMask = 0x0ffff // 所有
}