沙盒中的目录
AppName.app
- 内容:此目录包含了应用程序及其所有资源文件。
- 读写操作:不能写入该目录,可以对应用程序包中存储的任何资源进行只读访问。
- iTunes和iCloud:不支持iTunes或iCloud。
Documents/
- 内容:可以将应用程序的数据文件保存在此目录下。不过这些数据类型仅限于不可再生的数据,可再生的数据文件应该存放在Library/Cache目录下。苹果建议将程序中建立的或在程序中浏览到的文件数据保存在该目录下。
- iTunes和iCloud:备份到iTunes或iCloud。
Documents/Inbox
- 内容:该目录用来保存由外部应用请求当前应用程序打开的文件。
- 读写操作:应用程序可以读取和删除该目录中的文件,但不能创建新文件或写入现有文件。如果用户试图在这个目录中编辑一个文件,你的应用程序必须在任何更改之前默默地将其移动到目录之外。
- iTunes和iCloud:备份到iTunes或iCloud。
Library/
- 内容:苹果建议用来存放默认设置或其它状态信息。
- iTunes和iCloud:备份到iTunes或iCloud。但是要除了Caches子目录。
Library/Caches
- 内容:主要是缓存文件,用户使用过程中缓存都可以保存在这个目录中。前面说过,Documents目录用于保存不可再生的文件,那么这个目录就用于保存那些可再生的文件,比如网络请求的数据。鉴于此,应用程序通常还需要负责删除这些文件。
- iTunes和iCloud:不支持备份到iTunes或iCloud
Library/Preferences
- 内容:应用程序的偏好设置文件。我们使用NSUserDefaults写的设置数据都会保存到该目录下的一个plist文件中。
- iTunes和iCloud:备份到iTunes或iCloud
tmp
- 内容:各种临时文件,保存应用再次启动时不需要的文件。而且,当应用不再需要这些文件时应该主动将其删除,因为该目录下的东西随时有可能被系统清理掉,目前已知的一种可能清理的原因是系统磁盘存储空间不足的时候。
- iTunes和iCloud:备份到iTunes或iCloud
常见数据缓存
Foundation对象
保存在沙盒Documents或Library/Preferences目录下,可以通过plist、NSUserDefaults、NSKeyedArchiver技术来保存。
常见数据类型
保存在沙盒Documents或Library/Preferences目录下,可以通过NSUserDefaults技术来保存。
自定义的对象
保存在沙盒Documents目录下,可以通过NSKeyedArchiver技术来保存。
图片资源
- 把图片转为base64的字符串存到数据库中或者plist文件中,然后用到的时候再取出来
//获取沙盒路径,
NSString *path_sandox = NSHomeDirectory();
//创建一个存储plist文件的路径
NSString *newPath = [path_sandox stringByAppendingPathComponent:@/Documents/pic.plist];
NSMutableArray *arr = [[NSMutableArray alloc] init];
UIImage *image = [UIImage imageNamed:@"1.png"];
NSData *_data = UIImageJPEGRepresentation(image, 1.0f);
//将图片的data转化为字符串
NSString *strimage64 = [_data base64EncodedString];
[arr addObject:image64];
//写入plist文件
[arr writeToFile:newPath atomically:YES];
NSData *_decodedImageData = [[NSData alloc]initWithBase64EncodedString:strimage64 options:NSDataBase64DecodingIgnoreUnknownCharacters];
UIImage *_decodedImage = [UIImage imageWithData:_decodedImageData];
- 把图片直接保存到沙盒中,然后再把路径存储起来,等到用图片的时候先获取图片的路径,再通过路径拿到图片
//拿到图片
UIImage *image2 = [UIImage imageNamed:@"1.png"];
NSString *path_document = NSHomeDirectory();
//设置一个图片的存储路径
NSString *imagePath = [path_document stringByAppendingString:@"/Documents/pic.png"];
//把图片直接保存到指定的路径(同时应该把图片的路径imagePath存起来,下次就可以直接用来取)
[UIImagePNGRepresentation(image2) writeToFile:imagePath atomically:YES];
- 从本地相册中获取图片并上传到服务器时,先将图片压缩保存到app沙盒Library/Caches目录下,再将图片上传。
获取各目录路径的方法
- 沙盒目录
NSHomeDirectory()
- AppName.app
[[NSBundle mainBundle] bundlePath]
- tmp
NSTemporaryDirectory()
- Documents
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *docPath = [paths objectAtIndex:0];
缓存数据的方式
plist文件
直接写文件方式plist:可以存储的对象有NSString、NSArray、NSDictionary、NSData、NSNumber。也可以通过代码的方式进行读写,方法如下:
NSDictionary *addDic = @{@"name" : @"dev",
@"age" : @"24"};
//将字典保存到document文件->获取appdocument路径
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
//要创建的plist文件名 -> 路径
NSString *filePath = [docPath stringByAppendingPathComponent:@"cityPlist.plist"];
//将字典写入文件
[addDic writeToFile:filePath atomically:YES];
//读取文件
NSMutableDictionary *plistDic = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
NSUserDefaults
- 每个应用都有一个NSUesrDefaults实例,通过它可以存储应用配置信息以及用户信息,比如保存用户名、密码、字体大小、是否自动登录等等。数据自动保存在沙盒的Libarary/Preferences目录下。同样,该方法只能存取NSString、NSArray、NSDictionary、NSData、NSNumber类型的数据。
- 由于属性列表本身不加密,所以安全性几乎可以说为零。因为,属性列表正常用于存储少量的并且不重要的数据。
- 在程序启动后,系统会自动创建一个NSUserDefaults的单例对象,我们可以获取这个单例来存储少量的数据,它会将输出存储在.plist格式的文件中。其优点是像字典一样的赋值方式方便简单,但缺点是无法存储自定义的数据。
- 如果需要存储plist文件不支持的类型,比如图片,可以先将其归档为NSData类型,再存入plist文件。
// 存
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:@"jack" forKey:@"firstName"];
[defaults setInteger:10 forKey:@"Age"];
UIImage *image =[UIImage imageNamed:@"somename"];
NSData *imageData = UIImageJPEGRepresentation(image, 100);//把image归档为NSData
[defaults setObject:imageData forKey:@"image"];
[defaults synchronize];
// 读
NSString *firstName = [defaults objectForKey:@"firstName"];
NSInteger age = [defaults integerForKey:@"Age"];
NSData *imageData = [defaults dataForKey:@"image"];
UIImage *image = [UIImage imageWithData:imageData];
- NSUserDefaults提供了若干简便方法可以存储某些常用类型的值,例如:
setBool:forKey:
setFloat:forKey:
setInteger:forKey:
setDouble:forKey:
setURL:forKey:
NSKeyedArchiver
把对象转为字节码加密,以文件的形式存储到磁盘上,程序运行过程中或者当再次重写打开程序的时候,可以通过解归档(反序列化)还原这些对象。归档的对象包括:Foundation框架中对象、自定义的对象、自定义的内容。
- 归档Foundation对象
// 获得文件路径
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [documentPath stringByAppendingPathComponent:@"file.archiver"];
// 归档(序列化)
NSArray *archiveAry = @[@"dev",@"iOS"];
[NSKeyedArchiver archiveRootObject: archiveAry toFile:filePath];
//解归档(反序列化)
NSArray *unArchiveAry = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
- 归档自定义的内容
// 获得文件路径
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [documentPath stringByAppendingPathComponent:@"file.archiver"];
// 1. 使用NSMutableData存放归档数据
NSMutableData *archiverData = [NSMutableData data];
// 2. 创建归档对象
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:archiverData];
// 3. 添加归档内容 (设置键值对)
[archiver encodeObject:@"dev" forKey:@"name"];
[archiver encodeInt:24 forKey:@"age"];
[archiver encodeObject:@[@"iOS",@"OC"] forKey:@"language"];
// 4. 完成归档
[archiver finishEncoding];
// 5. 将归档的信息存储到磁盘上
[archiverData writeToFile:filePath atomically:YES];
// 解归档
// 1. 从磁盘读取文件,生成NSData实例
NSData *unarchiverData = [NSData dataWithContentsOfFile:filePath];
// 2. 根据Data实例创建和初始化解归档对象
NSKeyedUnarchiver *unachiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:unarchiverData];
// 3. 解归档,根据key值访问
NSString *name = [unachiver decodeObjectForKey:@"name"];
int age = [unachiver decodeIntForKey:@"age"];
NSArray *ary = [unachiver decodeObjectForKey:@"language"];
- 归档自定义的对象
// RYJPerson.h
@interface RYJPerson : NSObject<NSCoding>
@property (nonatomic,copy) NSString* name;
@property (nonatomic,assign) NSInteger age;
@property (nonatomic,assign) NSInteger number;
@end
// RYJPerson.m
@implementation RYJPerson
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super init]) {
self.name = [aDecoder decodeObjectForKey:@"name"];
self.age = [aDecoder decodeIntegerForKey:@"age"];
self.number = [aDecoder decodeIntegerForKey:@"number"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeInteger:self.age forKey:@"age"];
[aCoder encodeInteger:self.number forKey:@"number"];
}
@end
RYJPerson *Person = [[RYJPerson alloc] init];
Person.name = @"dev";
Person.age = 24;
Person.number = 110;
// 创建路径
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES)lastObject];
NSString *accountPath = [documentPath stringByAppendingPathComponent:@"Account.data"];
// 存
[NSKeyedArchiver archiveRootObject:Person toFile:accountPath];
// 读
RYJPerson *account = [NSKeyedUnarchiver unarchiveObjectWithFile:accountPath];
SQLite3
Core Data
关于APP更新后沙盒缓存的问题
- 程序升级的只是.app文件,document和library不会被清理,会被iTunes和icloud同步,但是caches和tmp目录下的文件会被清理。
- 更新后沙盒中的路径是会变的,但只要是通过苹果的API获取的,无论路径变成怎样的,都能取得正确的沙盒路径。所以应该保存相对路径而不应该保存绝对路径。
关于Xcode run操作后的沙盒缓存问题
关于此问题做了以下实验:
(实验前在Documents、Library\Caches、Library\Preferences、tmp目录下各存了一个plist文件,并删除了存入文件的代码)
直接run和杀死进程后run操作,沙盒中所有目录下的文件都没有变化。
删除app后运行run,沙盒中的所有目录下文件都消失。