什么是沙盒机制
数据持久化
是数据的永久存储;为什么要做数据持久化:存储在内存中的数据,程序关闭,内存释放,数据丢失。这种数据是临时的;数据持久化的本质:数据保存成文件,存储到程序的沙盒。
沙盒机制
沙盒机制
1.每一个App安装到手机上(或者模拟器上)都会自动生成三个文件夹 这三个文件夹 可以理解为这个APP的沙盒
2.并且每个APP的文件夹都是相对独立的 只能自己的应用去访问 不可以互相访问
3.文件夹中 存储的是 代码以外的 所有数据 例如 (图片素材 声音 视频 文档等) 也就是说持久化文件(缓存文件)可以存储到 文件夹中
通过代码查找程序沙盒相对路径
NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory directory,NSSearchPathDomainMask domainMask,BOOL expandTilde);
获取沙盒目录路径的方法
NSHomeDirectory——————->沙盒主路径
NSDocumentDirectory————>Documents文件夹
NSLibraryDirectory——————>Library文件夹
NSCachesDiectory——————>Caches文件夹
NSTemporaryDirectory()———>tmp文件夹
// 打印沙盒的每个文件夹路径
- (void)path
{
/*
每一次运行的时候 都是重新安装的过程
都会随机生成一个新的 沙盒路径 (名字是随机的)
注意:要获取的是当前的沙盒路径
*/
// 打印沙盒路径
NSString *appPath = NSHomeDirectory();
NSLog(@"%@", appPath);
// Documents文件夹
// 可以被iTunes备份 可以保存一些用户的数据 及缓存文件等
// NSDocumentationDirectory 要获取的文件夹路径
// NSUserDomainMask 搜索的范围
// YES 是否获取全路径
NSArray *document = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath = document[0];
NSLog(@"%@", documentPath);
// 获取Library 文件夹路径
// Library 可以被iTunes备份
// Caches 主要存储系统缓存文件
// Preferences 系统配置文件
NSArray *library = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryPath = library[0];
NSLog(@"%@", libraryPath);
// 获取tmp 文件夹
// 注意存储临时文件
// 当手机重新启动时 该文件夹的文件 会被删除
// 有可能 不重启 也会被删除
NSString *tmpPath = NSTemporaryDirectory();
NSLog(@"%@", tmpPath);
}
简单对象写入文件
// 简单对象的写入
// 系统类实例出来的对象 叫简单对象
// 例如:字符串 数组 字典 二进制对象(NSData)
// 如果要写入一个数组或者字典等容器类对象
// 那么这个容器当中也要保存是 简单对象才能写入
- (void)writeFile
{
// 把字符串 存储到沙盒当中
NSString *str = @"第一章 盘古开天";
// xiaoshuo.txt
// 拼接文件存储的路径
NSString *filePath = [kDocument stringByAppendingPathComponent:@"/xiaoshuo.txt"];
// 进行简单对象的写入
// 在写入过程中 出现意外情况 也可以写入成功
NSError *error = nil;
[str writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:&error];
NSLog(@"%@", filePath);
// 写入一个数组
NSArray *arr = @[@"zhangwen", @"zhuangzhuang", @"zhaojie", @"xuyang"];
// 获取写入的路径
NSString *arrPath = [kDocument stringByAppendingPathComponent:@"/arr.plist"];
// 写入文件
[arr writeToFile:arrPath atomically:YES];
NSLog(@"%@", arrPath);
// 写入一个字典
NSDictionary *dic = @{@"name":@"jingxiaojian", @"sex":@"male"};
NSString *dicPath = [kDocument stringByAppendingPathComponent:@"/dic.plist"];
[dic writeToFile:dicPath atomically:YES];
NSLog(@"%@", dicPath);
// 写入data数据
NSString *dataStr = @"哈哈哈";
NSData *data = [dataStr dataUsingEncoding:NSUTF8StringEncoding];
NSString *dataPath = [kDocument stringByAppendingPathComponent:@"/data"];
[data writeToFile:dataPath atomically:YES];
NSLog(@"%@", dataPath);
// data 文件一般是 存储 图片的
// UIImagePNGRepresentation 把图片转化成NSData
NSData *imageData = UIImagePNGRepresentation([UIImage imageNamed:@"w4"]);
NSString *imagePath = [kDocument stringByAppendingPathComponent:@"/imageData"];
[imageData writeToFile:imagePath atomically:YES];
NSLog(@"%@", imagePath);
// 读取数据
- (void)readFile
{
// 获取写入的路径
NSString *arrPath = [kDocument stringByAppendingPathComponent:@"/arr.plist"];
// 从该路径进行读取
NSArray *arr = [NSArray arrayWithContentsOfFile:arrPath];
NSLog(@"%@", arr);
// 读取data 图片
// 拼接路径
NSString *imageDataPath = [kDocument stringByAppendingPathComponent:@"/imageData"];
NSData *data = [NSData dataWithContentsOfFile:imageDataPath];
UIImage *image = [UIImage imageWithData:data];
}
}
NSFileManager
管理文件的一个类
单例类
可以对文件进行 创建 移动 复制 删除
// 创建文件夹方法
- (void)createFile
{
// 获取要创建文件夹的路径
NSString *path = [kDocuments stringByAppendingPathComponent:@"/DownLoad"];
NSLog(@"%@", path);
// 创建文件管理器
NSFileManager *manager = [NSFileManager defaultManager];
// 创建文件夹
// withIntermediateDirectories
// 是否覆盖之前的文件 如果是NO 就是不覆盖
// 不覆盖就相当于 创建文件夹失败
BOOL isCreate = [manager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
// 打印是否创建成功
NSLog(@"%d", isCreate);
}
// 移动文件夹
- (void)moveFile
{
// 获取原路径
NSString *oldPath = [kDocuments stringByAppendingPathComponent:@"/DownLoad"];
// 获取新路径
NSString *newPath = [kCaches stringByAppendingPathComponent:@"/DownLoad"];
// 创建文件管理对象
NSFileManager *manager = [NSFileManager defaultManager];
// 移动文件夹(从老的移动到新的路径)
BOOL isMove = [manager moveItemAtPath:oldPath toPath:newPath error:nil];
NSLog(@"%d", isMove);
}
// 拷贝文件夹
- (void)copyFile
{
// 获取原路径
NSString *oldPath = [kCaches stringByAppendingPathComponent:@"/DownLoad"];
// 获取新路径
NSString *newPath = [kDocuments stringByAppendingPathComponent:@"/DownLoad1"];
// 创建文件管理对象
NSFileManager *manager = [NSFileManager defaultManager];
// 拷贝(原路径的文件夹 没有被删掉 拷贝了一份到新路径)
BOOL isCopy = [manager copyItemAtPath:oldPath toPath:newPath error:nil];
NSLog(@"%d", isCopy);
}
// 删除文件夹
- (void)removeFile
{
// 获取路径
NSString *path = [kDocuments stringByAppendingPathComponent:@"/DownLoad"];
NSFileManager *manager = [NSFileManager defaultManager];
BOOL isRemove = [manager removeItemAtPath:path error:nil];
NSLog(@"%d", isRemove);
}
// 判断文件夹是否存在
- (void)isExist
{
NSString *path = [kDocuments stringByAppendingPathComponent:@"/DownLoad1"];
NSFileManager *manager = [NSFileManager defaultManager];
BOOL isExist = [manager isExecutableFileAtPath:path];
NSLog(@"%d", isExist);
}
复杂对象写入文件
复杂对象写入步骤:
1.遵守 NScoding(需要在写入的时候 按照一定的规则 进行写入 一定的编码格式去写入) 归档与反归档(序列与反序列)
2.重写(协议中) 归档 与 反归档方法
3.创建一个复杂对象出来
4.创建一个归档对象
5.把复杂对象利用归档对象 转化成data
6.把data写入文件 进行数据持久化
新建一个类继承于NSobject
添加属性
@property (nonatomic, retain) NSString *name;
@property (nonatomic, assign) NSInteger age;
@property (nonatomic, retain) NSData *imageData;
在.m文件中
// 归档方法
- (void)encodeWithCoder:(NSCoder *)aCoder
{
// 按照一定的编码格式归档
// 注意:归档时候的key 要与 反归档时候一致
[aCoder encodeObject:self.name forKey:@"name"];
// 要选用 与属性类型 一致的解码方法
[aCoder encodeInteger:self.age forKey:@"age"];
// 一般统一使用对象类型
[aCoder encodeObject:self.imageData forKey:@"imageData"];
}
// 反归档方法
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
// 按照一定编码格式 和 存储的key标识 取出被归档的对象(反归档)
self.name = [aDecoder decodeObjectForKey:@"name"];
self.age = [aDecoder decodeIntegerForKey:@"age"];
self.imageData = [aDecoder decodeObjectForKey:@"imageData"];
}
return self;
}
在RootViewController.m中
// 复杂对象的写入文件
// 自己创建出来的类(例如)Student类
// 写入的核心思想:
// 把复杂对象 转化成 简单对象 进行写入
// 一般转换成NSData对象进行写入
Student *stu = [[Student alloc] init];
stu.name = @"jtt";
stu.age = 24;
stu.imageData = UIImagePNGRepresentation([UIImage imageNamed:@"2014.jpg"]);
// 创建一个可变data
NSMutableData *data = [NSMutableData data];
// 创建一个归档对象
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
// 将复杂对象 通过归档对象 转化成data
[archiver encodeObject:stu forKey:@"student"];
// 完成归档
[archiver finishEncoding];
// 注意:
// 实际上 通过 归档对象 把 复杂对象 写入 data中
// 并且写入的标识 就key
// 归档与反归档不是数据持久化
// 只是把复杂对象 按照系统编码格式 转化成data
// 真正持久化 还是写入文件
//NSLog(@"%@", data);
// 获取路径
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
// 拼接路径
NSString *path = [documentPath stringByAppendingPathComponent:@"/SaveStudent"];
// 写入文件
[data writeToFile:path atomically:YES];
// 释放归档对象
[archiver release];
NSLog(@"%@", path);
// 反归档
// 从沙盒中读取data数据
NSData *newData = [NSData dataWithContentsOfFile:path];
// 创建反归档对象(利用data创建)
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:newData];
// 利用反归档对象 反归档出复杂对象
Student *stuNew = [unarchiver decodeObjectForKey:@"student"];
// 调用完成 返回归档
[unarchiver finishDecoding];
[unarchiver release];
UIImage *image = [UIImage imageWithData:stuNew.imageData];
// 如何把一个数组的 复杂对象 写到文件中
// 便利这个数组 把每一个复杂对象
// 转化成简单对象(data)
// 然后 再将data 保存到一个数组中
// 最后 直接把数组写到文件中 进行持久化