前言
本系列文章主要介绍内存缓存和磁盘缓存的相关用法和原理。磁盘缓存其实就是 数据持久化。本文对 iOS 中常用的数据持久化方案进行介绍,主要有以下几种方案:
- plist文件(属性列表)
- preference(偏好设置)
- NSKeyedArchiver(归档)
- SQLite 3
- CoreData
沙盒
在介绍各种数据持久化方案之前,先介绍下沙盒的机制和结构:iOS程序默认情况下只能访问程序自己的目录,这个目录被称为“沙盒”。结构如下:
- 应用程序包
- Documents
- Library
- Caches
- Preferences
- tmp
- 应用程序包
- 这里面存放的是应用程序的源文件,包括资源文件和可执行文件。比如 各种bundle文件
NSString *path = [[NSBundle mainBundle] bundlePath];
- Documents
- 数据持久化最常用的目录,适合存储重要数据,并将通过iCloud自动备份。
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
- Library/Caches
- 适合存储体积大,不需要备份的非重要数据。
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
- Library/Preferences
- 通常保存应用的设置信息。
- tmp:
- 系统可能在应用没运行时就删除该目录下的文件,所以此目录适合保存应用中的一些临时文件,用完就删除。
数据持久化方案
plist文件
- 适用于
- NSArray;NSMutableArray;NSDictionary;NSMutableDictionary;NSData;NSMutableData;NSString;NSMutableString;NSNumber;NSDate;
- 使用方法
- 获得文件路径
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject; ```
NSString *fileName = [path stringByAppendingPathComponent:@”123.plist”];
``` - 存储
NSArray *array = @[@"123", @"456", @"789"]; [array writeToFile:fileName atomically:YES];
-
读取
NSArray *result = [NSArray arrayWithContentsOfFile:fileName];
- 获得文件路径
Preference
- 使用方法
//1.获得NSUserDefaults文件
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
//2.向文件中写入内容
[userDefaults setObject:@"AAA" forKey:@"a"];
[userDefaults setBool:YES forKey:@"sex"];
[userDefaults setInteger:21 forKey:@"age"];
//2.1立即同步
[userDefaults synchronize];
//3.读取文件
NSString *name = [userDefaults objectForKey:@"a"];
BOOL sex = [userDefaults boolForKey:@"sex"];
NSInteger age = [userDefaults integerForKey:@"age"];
NSLog(@"%@, %d, %ld", name, sex, age);
- 注意
- Preference是专门用来保存应用程序的配置信息的,一般不要在Preference中保存其他数据。
- 如果没有调用synchronize方法,系统会根据I/O情况不定时刻地保存到文件中。所以如果需要立即写入文件的就必须调用synchronize方法。
- 偏好设置会将所有数据保存到同一个文件中。即preference目录下的一个以此应用包名来命名的plist文件。
NSKeyedArchiver
- 适用于
- 遵循NSCoding协议
```
@interface Person : NSObject@property (strong, nonatomic) UIImage *avatar; @property (copy, nonatomic) NSString *name; @property (assign, nonatomic) NSInteger age; @end //解档 - (id)initWithCoder:(NSCoder *)aDecoder { if ([super init]) { self.avatar = [aDecoder decodeObjectForKey:@”avatar”]; self.name = [aDecoder decodeObjectForKey:@”name”]; self.age = [aDecoder decodeIntegerForKey:@”age”]; } return self; } //归档
-
(void)encodeWithCoder:(NSCoder *)aCoder { [aCoder encodeObject:self.avatar forKey:@”avatar”]; [aCoder encodeObject:self.name forKey:@”name”]; [aCoder encodeInteger:self.age forKey:@”age”]; ```
-
使用
//保存 NSString *file = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.data"]; Person *person = [[Person alloc] init]; person.avatar = self.avatarView.image; person.name = self.nameField.text; person.age = [self.ageField.text integerValue]; [NSKeyedArchiver archiveRootObject:person toFile:file]; //读取 NSString *file = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.data"]; Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:file]; if (person) { self.avatarView.image = person.avatar; self.nameField.text = person.name; self.ageField.text = [NSString stringWithFormat:@"%ld", person.age]; }