就是将数据保存在本地.
归档和返归档.
苹果手机为了保证自己数据上的绝对安全.设计了沙盒文件,每一个应用程序都配备了自己的沙河文件,每一次运行,文件夹的名字就会变成没有任何规律的字符串.
第一个参数: 当前前往哪一个文件夹,前往Documents文件用NSDocumentsDirectory, 64行. 还可以前往缓存Caches,对应68行.
第二个参数: 访问的文件夹类型,指定访问的是用户文件夹.
第三个参数: 绝对路径(YES); 相对路径(NO);
绝对路径是给系统来使用的, 系统可以通过当前的路径找到文件夹,我们在操作文件的时候都会用绝对路径;
相对路径只会把前往的文件夹显示,其他部分是~,告诉程序员要去哪个文件夹.
NSArray *sandBox = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSLog(@"%@",sandBox[0]);
沙盒中一共有3个文件.
1.Documents文件: 主要用来存储用户想要储存的一些信息,比如收藏的信息或者自己设置的一些内容,所以我们做收藏功能一般往这个文件夹里面写文件.
2.Library文件夹是方便程序开发者使用的,主要操作他的两个文件夹,caches和Preferences.
caches: 用来保存缓存文件,SDWebImage会把图片加到缓存文件中,所以清除缓存功能就是把这个文件夹删除.
Preferences 一般用来保存程序猿设置的信息,比如NSUserDefaults就会把数据存在这个文件夹中.
3.tmp文件: 一般存放临时内容.
之前在沙河中还有一个文件,.app文件,在新版本里已经被移除.
要把简单对象写入本地, 简单对象指的是NSString, NSArray等.
//1. 先通过数组获取沙盒路径.
NSArray *sandBox = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
// 从数组中获取沙盒路径.
NSString *sandBoxPath = sandBox[0];
// 给你要保存的文件拼出来路径, 因为Documents里什么都没有.拼接方式有两种:
// NSString *documentPath1 = [sandBoxPath stringByAppendingString:@"/刘鑫奇.txt"];
//
NSString *documentPath2 = [sandBoxPath stringByAppendingPathComponent:@"刘鑫奇.plist"];
// NSLog(@" 1路径 :%@",documentPath1);
NSLog(@" 2路径 :%@",documentPath2);
NSString *str = @"今天你要嫁给我吗?,lalaallalallalallala";
// 把字符串写入到本地.
// 第一个参数: 文件要保存的路径
// 第二个参数: 对文件进行保护,YES
// 第三个参数: 编码
// 第四个参数: 错误信息.
[str writeToFile:documentPath2 atomically:YES encoding:NSUTF8StringEncoding error:nil];
// 如果路径下有对应的文件,则会把原来的文件覆盖,如果没有则创建一个新文件.
//将沙盒文件读粗来
NSString *tempStr = [NSString stringWithContentsOfFile:documentPath2 encoding:NSUTF8StringEncoding error:nil];
NSLog(@"%@",tempStr);
//2.数组写入到本地
NSArray *arr = @[@"1",@"2",@"3",@"4",@"5"];
//1. 通过数组获取沙盒地址.
NSArray *sandBox = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
//用字符串保存沙盒路径
NSString *sandBoxPath = sandBox[0];
// 给药写入文件拼接路径
NSString *arrPath = [sandBoxPath stringByAppendingPathComponent:@"arr.plist"];
// 将数组写入本地
[arr writeToFile:arrPath atomically:YES];
NSLog(@"%@",arrPath);
// 把数组从本地读出来
NSArray *arrPlist = [NSArray arrayWithContentsOfFile:arrPath];
NSLog(@"%@",arrPlist);
// 把字典写入到本地.
NSDictionary *dic = @{@"男":@"刘鑫奇",@"女":@"高薪茹",@"孩":@"刘伊茹"};
NSArray *sandBox = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *sandBoxPath = sandBox[0];
NSString *dicPath = [sandBoxPath stringByAppendingPathComponent:@"dic.plist"];
[dic writeToFile:dicPath atomically:YES];
// 读取
NSDictionary *tempDic = [NSDictionary dictionaryWithContentsOfFile:dicPath];
for (NSString *key in tempDic) {
NSLog(@"%@:%@",key,tempDic[key]);
}
那么? 要是想要将一个自己写的model类写入本地呢?
如果想要实现归档和反归档的操作需要先签订一个协议 NSCoding. 有两个必须实现的方法.
我的model类是student
@interface StudentModel : NSObject<NSCoding>
@property(nonatomic, copy)NSString *name;
@property(nonatomic, copy)NSString *sex;
@property(nonatomic, copy)NSString *hobby;
@property(nonatomic, assign)NSInteger age;
// 针对这四条写一个自定义初始化.
- (instancetype)initWithName:(NSString *)name sex:(NSString *)sex hobby:(NSString *)hobby age:(NSInteger)age;
+ (StudentModel *)StudentWithName:(NSString *)name sex:(NSString *)sex hobby:(NSString *)hobby age:(NSInteger)age;
@end
#import "StudentModel.h"
@implementation StudentModel
- (instancetype)initWithName:(NSString *)name sex:(NSString *)sex hobby:(NSString *)hobby age:(NSInteger)age{
self = [super init];
if (self){
self.name = name;
self.sex = sex;
self.hobby = hobby;
self.age = age;
}
return self;
}
+ (StudentModel *)StudentWithName:(NSString *)name sex:(NSString *)sex hobby:(NSString *)hobby age:(NSInteger)age{
StudentModel *model = [[StudentModel alloc] initWithName:name sex:sex hobby:hobby age:age];
return model;
}
#pragma mark 签订完NSCoding协议之后,需要实现两个协议方法,一个是归档的时候使用,一个是反归档的时候使用.
- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:self.name forKey:@"姓名"];
[aCoder encodeObject:self.sex forKey:@"性别"];
[aCoder encodeObject:self.hobby forKey:@"爱好"];
[aCoder encodeInteger:self.age forKey:@"年龄"];
// 使用encode方法要和数据的类型相互匹配.
}
- (id)initWithCoder:(NSCoder *)aDecoder{
self = [super init];
if (self) {
// 把数据根据之前的Key反编译过来, 再对self赋值
self.name = [aDecoder decodeObjectForKey:@"姓名"];
self.hobby = [aDecoder decodeObjectForKey:@"爱好"];
self.sex = [aDecoder decodeObjectForKey:@"性别"];
self.age = [aDecoder decodeIntForKey:@"年龄"];
}
return self;
}
这些工作做好后, 我们就可以将复杂对象写入本地啦.
// 把复杂对象写入本地, 需要签订NSCoding协议
StudentModel *stu = [StudentModel StudentWithName:@"刘鑫狗儿" sex:@"男" hobby:@"高高" age:23];
// 通过数组获取沙盒路径
NSArray *sandBox = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *sandBoxPath = sandBox[0];
// 接下来拼接存放对象的文件夹路径,这个文件的扩展名可以是任意的.
NSString *stuPath = [sandBoxPath stringByAppendingPathComponent:@"学生信息.avi"];
// 对对象进行归档.
// 第一个参数: 要实施归档的对象.
// 第二个参数: 路径.
[NSKeyedArchiver archiveRootObject:stu toFile:stuPath];
NSLog(@"%@",stuPath);
// 返归档
StudentModel *newStu = [NSKeyedUnarchiver unarchiveObjectWithFile:stuPath];
NSLog(@"%@",newStu.name);
那么, 把复杂对象装入数组中保存呢?
// 把复杂对象存到数组中,保存.
StudentModel *stu1 = [StudentModel StudentWithName:@"刘鑫狗1" sex:@"男1" hobby:@"高薪茹1" age:23];
StudentModel *stu2 = [StudentModel StudentWithName:@"刘鑫狗2" sex:@"男2" hobby:@"高薪茹2" age:23];
StudentModel *stu3 = [StudentModel StudentWithName:@"刘鑫狗3" sex:@"男3" hobby:@"高薪茹3" age:23];
StudentModel *stu4 = [StudentModel StudentWithName:@"刘鑫狗4" sex:@"男4" hobby:@"高薪茹4" age:23];
NSArray *arr = @[stu1,stu2,stu3,stu4];
NSArray *sandBox = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *sandBoxPath = sandBox[0];
NSString *arrPath = [sandBoxPath stringByAppendingPathComponent:@"数组学生.avi"];
[NSKeyedArchiver archiveRootObject:arr toFile:arrPath];
NSLog(@"%@",arrPath);
// 反归档: 遍历学生姓名.
NSArray *newArr = [NSKeyedUnarchiver unarchiveObjectWithFile:arrPath];
for (StudentModel *stu in newArr) {
NSLog(@"姓名:%@ 爱好:%@",stu.name,stu.hobby);
}
* warning 总结: 数据持久化的步骤:
// 指定前往沙盒的哪一个文件夹.
// 用字符处接受沙盒路径.
// 拼接文件路径.
// 存入本地或者归档.*
如果复杂对象想要归档. 需要签订NSCoding协议,并且实现两个协议方法,放在数组里的复杂对象归档也要签协议.
那么, 想要添加一个文件夹呢?
#warning 文件管理者对文件夹进行操作
NSArray *sandBox = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *sandBoxPath = sandBox[0];
// 创建一个文件管理者
NSFileManager *manager = [NSFileManager defaultManager];
// 给要创建的文件夹拼接一个路径
NSString *newFilePath = [sandBoxPath stringByAppendingPathComponent:@"刘鑫奇"];
// 文件夹不需要有扩展名.
// 通过manager进行文件夹的创建.
[manager createDirectoryAtPath:newFilePath withIntermediateDirectories:YES attributes:nil error:nil];
NSLog(@"%@",newFilePath);
NSString *str = @"哈哈哈哈哈哈哈";
NSString *strPath = [newFilePath stringByAppendingPathComponent:@"str.txt"];
[str writeToFile:strPath atomically:YES encoding:NSUTF8StringEncoding error:nil];
NSLog(@"%@",strPath);
// 读取
NSString *newStr = [NSString stringWithContentsOfFile:strPath encoding:NSUTF8StringEncoding error:nil];
NSLog(@"%@",newStr);
// 删除文件夹
[manager removeItemAtPath:newFilePath error:nil];
如此, 我们就能够删除caches文件了.
// 删除Caches
NSArray *SandBox = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cachesPath = SandBox[0];
NSLog(@"%@",cachesPath);
[manager removeItemAtPath:cachesPath error:nil];