Title: iOS数据持久化
##数据持久化概念
数据持久化就是将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中的数据模型的统称。
##数据持久化的好处
1. 程序代码重用性强,即使更换数据库,只需要更改配置文件,不必重写程序代码。
2. 业务逻辑代码可读性强,在代码中不会有大量的SQL语言,提高程序的可读性。
3. 持久化技术可以自动优化,以减少对数据库的访问量,提高程序运行效率。
##iOS数据持久化方案
- NSUserDefault
- 文件存储 (包括:Plist属性列表、archive 归档、文件流)
- 钥匙串(keychain)
- 数据库相关 (Core Data、SQLite 3)
###沙盒机制
在iOS中每个APP都拥有自己的**沙盒**,APP**只能访问**对应沙盒中存储的数据, iOS是**不允许**跨越沙盒去访问数据的,所有的数据都是保存在该沙盒的三个子目录下。
###沙盒目录结构
```
应用程序.ipa
Documents
Library
\Caches
\Preferences
Temp
```
- `应用程序包`: 这里存放的是应用程序的源文件,包括资源文件和可执行文件。
```
NSString *ApplicationPath = [[NSBundle mainBundle] bundlePath];
```
- `Document`: 一般在该目录下保存一些比较重要的数据,当连接 iTunes后会自动同步数据。
```
NSString *DocumentPath = [NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES).firstObject];
```
`PS: 如果将数据资源保存到该目录.上架可能会被拒绝,(解决方案:直接设置该文件夹不被iTunes备份),总之:不能保存从网上下载的数据,否则不能上架。`
- `Library`: 存储应用设置或者状态信息等,在该目录下还有两个子目录: `Caches和Preference`
```
NSString *CachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject];
```
`Library/Caches`: 存放缓存文件,iTunes不会备份,因此文件不会因APP退出而删除(一般使用SDWebImage的缓存资源都是保存到这来)
`Library/Preference`: 保存应用的所有偏好设置,iOS的Setting(设置)会在该目录查找该应用的设置信息,iTunes会同步数据
- temp: 临时文件, iTunes不会备份该文件夹中的数据, 这个文件夹中的数据,会因为应用的关闭而删除。
```
NSString *tempPath = NSTemporaryDirectory( );
```
###NSUerDefault
小规模数据,弱业务相关数据,都可以放到`NSUserDefault`里面。
- 偏好设置是专门用来保存应用程序的配置信息的,一般不要在偏好设置中保存其他数据。
- 如果没有调用`synchronize`方法,系统会根据I/O情况不定时刻地保存到文件中。所以如果需要立即写入文件的就必须调用`synchronize`方法。
- 偏好设置会将所有数据保存到同一个文件中。即`preference`目录下的一个以此应用包名来命名的plist文件。
```
//1.获得NSUserDefaults文件
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
//2.向文件中写入内容
[userDefaults setObject:@"Barry" forKey:@"name"];
[userDefaults setBool:YES forKey:@"male"];
[userDefaults setInteger:20 forKey:@"age"];
//2.1立即同步
[userDefaults synchronize];
//3.读取文件
NSString *name = [userDefaults objectForKey:@"name"];
BOOL male = [userDefaults boolForKey:@"male"];
NSInteger age = [userDefaults integerForKey:@"age"];
NSLog(@"%@, %d, %ld", name, male, age);
```
###Plist
`plist文件存储`:是一种明文的轻量级存储方式,最常用的格式是XML格式,系统会提供一个info.plist文件,这种方式的安全性几乎为**0**,所以`plist`主要是用于存储少量并且不重要的数据。 `plist`只能读取数组(NSArray)或者字典(NSDictonary)。
```
/**
* Plist文件
*/
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *fileName = [path stringByAppendingPathComponent:@"Person.plist"];
NSDictionary *dict = @{
@"name" : @"Barry",
@"age" : @20,
@"height" : @1.80f
};
// 将数据写入Plist
[dict writeToFile:fileName atomically:YES];
NSLog(@"%@", fileName);
// 读取plist中的数据
NSDictionary *dicts = [NSDictionary dictionaryWithContentsOfFile:fileName];
NSLog(@"dict = %@",dicts);
NSString *str = [NSString stringWithContentsOfFile:fileName encoding:NSUTF8StringEncoding error:nil];
NSLog(@"str = %@", str);
```
###Keychain(钥匙串)
`Keychain` 是苹果提供的带有可逆加密的存储机制,普遍用在各种存密码的需求上。另外,由于App卸载只要系统不重装,`Keychain`中的数据依旧能够得到保留,以及可被`iCloud`同步的特性,大家都会在这里存储用户唯一标识串。所以有需要加密、需要存`iCloud`的敏感小数据,一般都会放在`Keychain`。
###数据归档/序列化(NSKeyedArchiver)
`NSKeyedArchiver`: 是一种轻量级存储的持久化方案,数据化归档时经过加密处理的,所以安全性远高于`plist`。数据归档可以存储一些复杂的对象,数据保存前会经过二进制处理。
- 遵循协议、设置属性
```
/*遵循 NSCoding 协议*/
@interface Student : NSObject
/*设置属性*/
@property(nonatomic, copy) NSString *name;
@property(nonatomic, assign) int age;
@property(nonatomic, copy) NSString *gender;
@end
```
```
/*解档(反序列化)*/
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self == [super init]) {
self.name = [aDecoder decodeObjectForKey:@"name"];
self.age = [aDecoder decodeIntForKey:@"age"];
self.gender = [aDecoder decodeObjectForKey:@"gender"];
}
return self;
}
/**归档(序列化)*/
- (void)encodeWithCoder:(NSCoder *)aCoder {
// 归档姓名(字符串对象)
[aCoder encodeObject:self.name forKey:@"name"];
// 归档年龄(注意:这是基本数据类型, 如果是其他的类型,直接调用对应类型的encode即可)
[aCoder encodeInteger:self.age forKey:@"age"];
[aCoder encodeObject:self.gender forKey:@"gender"];
}
@end
```
PS:
1. 必须遵循并实现NSCoding协议
2. 保存文件的扩展名可以任意指定
3. 继承时必须先调用父类的归档解档方法
###数据库(SQLite)
数据库(SQLite3): 是一个轻量级,跨平台的小型数据库,可移植性比较高,有着和`MySql`几乎相同的数据库语句,以及无需服务器即可使用的优点。
数据库的优点:
- 该方案可以存储大量的数据,存储和检索的速度非常快。
- 能对数据进行大量的聚合,这样比起使用对象来讲操作要快。
数据库的缺点:
- 它没有提供数据库的创建方式。
- 它的底层是基于C语言框架设计的,没有面向对象的API,用起来非常麻烦。
- 发杂的数据模型的数据建表,非常麻烦。
在实际开发中我们都是使用的是`FMDB`第三方开源的数据库,该数据库是基于`splite`封装的面向对象的框架。
###CoreData
`coreData`: 是苹果官方在iOS5之后推出的综合性数据库,其使用了对象关系映射技术,将对象转换成数据,将数据存储在本地的数据库中。
` coreData`为了提高效率,需要将数据存储在不同的数据库中,比如:在使用的时候,最好是将本地的数据保存到内存中,这样的目的是访问
速度比较快。
PS: CoreData并不是数据库!
使用了对象关系映射技术,将对象转换成数据,将数据存储在本地的数据库中。底层还是使用 SQLit3。
##下面一篇BLOG,将着重介绍第三方封装数据库`FMDB`的使用!