一,沙盒
iOS 中的沙盒机制(SandBox)是一种安全体系。
每个 iOS 应用程序都有一个单独的文件系统(存储空间),而且只能在对应的文件系统中进行操作,此区域被称为沙盒。所有的非代码文件都要保存在此,例如属性文件 plist、文本文件、图像、图标、媒体资源等。
Application:存放程序源文件,上架前经过数字签名,上架后不可修改,由于应用程序必须经过签名,所以不能在运行时对这个目录中的内容进行修改,否则会导致应用程序无法启动。
每个应用沙盒含有3个文件夹:Documents, Library 和 tmp
1,Documents:常用目录,iCloud备份目录,存放数据,这里不能存缓存文件,否则上架不被通过,保存应用程序的重要数据文件和用户数据文件等。iTunes 同步时会备份该目录
2,Library:
&Caches:保存应用程序使用时产生的支持文件和缓存文件,还有日志文件最好也放在这个目录。iTunes 同步时不会备份该目录。比如下载的音乐,视频,SDWebImage缓存等
&Preference:设置目录,iCloud会备份设置信息
3,tmp:存放临时文件,不会被备份,而且这个文件下的数据有可能随时被清除的可能,按照官方说法每三天清理一次缓存数据.
对于上述描述可以这样举例理解,一个记事本应用,用户写的东西需要保存起来,这些东西是用户自行生成的,则需要放在 Documents 目录里。一个新闻应用,如果需要从服务器下载东西展示给用户看,下载的东西就放在 Library/Caches 目录里。苹果审核对这个要求很严格,主要原因是 iCloud 的同步问题。
(1).获取沙盒文件对应的存储路径
//沙盒的根路径
NSString *rootPath = NSHomeDirectory();
//获取Documents目录
//[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//获取Library路径
//[NSHomeDirectory() stringByAppendingPathComponent:@"Library"];
NSArray *libPaths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryDirectory = [libPaths objectAtIndex:0];
//获取Library路径下的catch 路径
NSArray *cacPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cachePath = [cacPath objectAtIndex:0];
//[NSHomeDirectory() stringByAppendingPathComponent:@"tmp"];
NSString *tmp = NSTemporaryDirectory();
//拼接路径
NSString *tempFilePath = [tmp stringByAppendingPathComponent:@".File"];
}
(2).使用NSFileManager操作文件
NSString *mypath = @"你要操作的文件路径";
//拼接路径
NSString *doctorPath = [mypath stringByAppendingPathComponent:@"test"];
//创建文件管理器对象
NSFileManager *manager = [NSFileManager defaultManager];
//创建文件夹
NSError *error = nil;
BOOL iscreateSuccess = [manager createDirectoryAtPath:doctorPath withIntermediateDirectories:YES attributes:nil error:&error];
//创建文件
NSString *filePath = [doctorPath stringByAppendingPathComponent:@"test.txt"];
NSData *filecontent = [@"hello world" dataUsingEncoding:NSUTF8StringEncoding];
BOOL iscreateFileOk = [manager createFileAtPath:filePath contents:filecontent attributes:nil];
//写入数据到文件
BOOL isWriteOk = [@"mydata for me" writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
//读取数据
//1 NSData *data = [NSData dataWithContentsOfFile:filePath];
NString datacontent = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
//删除文件
BOOL isDeleteOk = [manager removeItemAtPath:filePath error:nil];
二,使用 plist存储
特点:(1)只能存储OC常用数据类型(NSString、NSDictionary、NSArray、NSData、NSNumber等类型)而不能直接存储自定义模型对象
(2).如果想存储自定义模型对象 -> 只能将自定义模型对象转换为字典存储;
(3).使用前提条件:一个对象必须实现了writeToFile方法,因为我们是通过调用对象的writeToFile方法将对象写入到一个plist文件中的
(4). plist只能识别字典,数组
获取文件路径,同上沙盒路径
//文件存储的位置(同上)
+(NSString*)getFilePath{
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
//拼接要保存的路径
NSString *filePath = [path stringByAppendingPathComponent:FILEPATH];
return filePath ;
}
写入要存储的数据
+(void)writeToFile:(id)data{
if ([data isKindOfClass:[NSDictionary class]]) {
NSDictionary *dicdata = (NSDictionary *)data ;
[dicdata writeToFile:[MyPlist getFilePath] atomically:YES];
}else if([data isKindOfClass:[NSArray class]]){
NSArray *arrdata = (NSArray*)data ;
[arrdata writeToFile:[MyPlist getFilePath] atomically:YES];
}else{
NSLog(@"error");
}
}
读取plist文件数据
+(id)readFromFile{
Boolean isdictionary = YES ;
if(isdictionary){
NSDictionary *dic = [NSDictionary dictionaryWithContentsOfFile:[MyPlist getFilePath]];
return dic ;
}else{
NSArray *array = [NSArray arrayWithContentsOfFile:[MyPlist getFilePath]];
return array ;
}
}
三,归档 NSKeyedArchiver
这个有点像java序列化serializable
特点:
(1).可以存储自定义模型对象
NSKeyedArchiver归档相对较plist存储而言,它可以直接存储自定义模型对象,而plist文件需要将模型转为字典才可以存储自定义对象模型;
(2).归档不能存储大批量数据(相比较Sqlite而言),存储数据到文件是将所有的数据一下子存储到文件中,从文件中读取数据也是一下子读取所有的数据;
缺点:
(3).假如你的文件中有多个对象,然后你想在利用归档添加一个对象,你需要先把所有的数据解档出来,然后再加入你想添加的那个对象,同理,你想删除一个文件中的一个对象也是,需要解档出所有的对象,然后将其删除。这样处理性能低下
(4).关于使用:需要归档的模型类必须要遵守NSCoding协议,然后模型实现类中必须实现两个方法:1>encodeWithCoder -> 归档;2> initWithCoder: - > 解档
(5). 使用注意:
如果父类也遵守了NSCoding协议,请注意:
应该在encodeWithCoder:方法中加上一句
[super encodeWithCode:encode];
// 确保继承的实例变量也能被编码,即也能被归档
应该在initWithCoder:方法中加上一句
self = [super initWithCoder:decoder];
// 确保继承的实例变量也能被解码,即也能被恢复
// 1. 自定义模型类Person
// 1.1 Person.h文件
#import <Foundation/Foundation.h>
// 只要一个自定义对象想要归档,必须要遵守NSCoding协议,并且要实现协议的方法
@interface Person : NSObject<NSCoding>
@property (nonatomic, assign) int age;
@property (nonatomic, strong) NSString *name;
@end
// 1.2 .m实现文件
#import "Person.h"
#define KName @"name"
#define KAge @"age"
@implementation Person
// 什么时候调用:当一个对象要归档的时候就会调用这个方法归档
// 作用:告诉苹果当前对象中哪些属性需要归档
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:_name forKey:KName];
[aCoder encodeInt:_age forKey:KAge];
}
// 什么时候调用:当一个对象要解档的时候就会调用这个方法解档
// 作用:告诉苹果当前对象中哪些属性需要解档
// initWithCoder什么时候调用:只要解析一个文件的时候就会调用
- (id)initWithCoder:(NSCoder *)aDecoder
{
#warning [super initWithCoder]
if (self = [super init]) {
// 解档
// 注意一定要记得给成员属性赋值
_name = [aDecoder decodeObjectForKey:KName];
_age = [aDecoder decodeIntForKey:KAge];
}
return self;
}
@end
// 2. 实例 -基本使用:取 / 存 数据
// 归档
[NSKeyedArchiver archiveRootObject: self.persons toFile:KFilePath];// 将self.persons模型对象数组
// 解档
_persons = [NSKeyedUnarchiver unarchiveObjectWithFile:KFilePath];