第一部分:沙盒Sandbox部分
沙盒Sandbox机制
每个iOS应用都有一个自己的“沙盒”,来服务自己.沙盒中保存着所有的非代码文件,例如图像,图标,声音,映像,属性列表,文本文件等.
“沙盒”有以下特点:
- 应用程序不能翻过自己的围墙去访问别的存储空间的内容
- 应用程序间不能共享数据,沙盒里的文件不能被复制到其他应用程序文件夹中,也不能把其他应用程序文件夹中的文件复制到沙盒里。
- 苹果禁止任何读、写沙盒以外的文件,禁止应用程序将内容写到沙盒以外的文件夹中。
- 应用程序请求的数据都要通过权限检测,假如不符合条件的话,不会被放行。
沙盒目录
iPhone沙盒下有四个文件夹,目录结构如下图:目录分析:
- Documents: 这个目录用于存储用户数据或其它应该定期备份的信息,iTunes会自动备份该目录. 例如游戏的进度数据
- Library: 这个目录下有两个子目录:Caches 和 Preferences
Preferences: 包含应用程序的偏好设置文件。您不应该直接创建偏好设置文件,而是应该使用NSUserDefaults类来取得和设置应用程序的偏好. - Caches: 存放缓存文件,iTunes不会备份此目录,此目录下文件不会在应用退出删除,一般存放体积比较大,不是很重要的资源,应用程序再次启动过程中需要的信息。
- tmp 目录:这个目录用于存放临时文件,保存应用程序再次启动过程中不需要的信息,使用完毕后再将相应的文件从该目录删除,应用没有运行时,系统也可能会自动清理该目录下的文件,iTunes不会同步该目录,iPhone重启时该目录下的文件会丢失。
再次强调:iTunes在与iPhone同步时,备份所有的Documents和Library目录下的文件。iPhone重启之后,会删除所有的tmp目录下的文件。
获取沙盒路径
获取沙盒路径有两种方式,一种是NSHomeDirectory()的形式,一种是NSSearchPathForDirectoriesInDomains()的形式
NSHomeDirectory()的形式:
- documents路径
NSString *home = NSHomeDirectory();
NSString *documentsPath = [home stringByAppendingPathComponent:@"Documents"]; // 不建议采用,因为新版本的操作系统可能会修改目录名
NSLog(@"%@",documentsPath);
- tmp路径
NSString *tmpPath = NSTemporaryDirectory();
NSLog(@"%@",tmpPath);
- documents路径
// 在某个范围内容搜索文件夹的路径 // directory:获取哪个文件夹.这里:NSUserDomainMask 代表从用户文件夹下找
// domainMask:在哪个范围下获取 NSUserDomainMask:在用户的范围内搜索
// expandTilde是否展开全路径, NO:~(选NO存commond+G不进去) YES:显示全路径
NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); // 在iOS中,只有一个目录跟传入的参数匹配,所以这个集合里面只有一个元素:
NSString *documentsPath = [array objectAtIndex:0];
NSLog(@"%@",documentsPath);
- Preferences路径
NSString *preferenceParh = NSSearchPathForDirectoriesInDomains(NSPreferencePanesDirectory, NSUserDomainMask, YES)[0];
NSLog(@"preferencePath:%@",preferenceParh);
- Caches路径
NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
NSLog(@"cache:%@",cachePath);
指定沙盒存储验证
范例
- 保存到'Documents'下:
NSString *str = @"123";
NSString *home = NSHomeDirectory();
NSString *documents = [home stringByAppendingPathComponent:@"Documents"]; // 不建议采用,因为新版本的操作系统可能会修改目录名
NSString *documentsfilePath = [documents stringByAppendingPathComponent:@"person.txt"];// 拼接文件名
NSLog(@"%@",documentsfilePath);
[str writeToFile:documentsfilePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
- 保存到'tmp'下:
// tmp
NSString *tmpPath = NSTemporaryDirectory();
NSString *tmpfilePath = [tmpPath stringByAppendingPathComponent:@"person.txt"];// 拼接文件名
NSLog(@"%@",tmpfilePath);
[str writeToFile:tmpfilePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
//读取再保存
NSString *redStr = [NSString stringWithContentsOfFile:tmpfilePath encoding:NSUTF8StringEncoding error:nil];
NSLog(@"read:%@",redStr);
NSString *continue2 = [redStr stringByAppendingString:@"噜啦啦啦噜啦啦"];
[continue2 writeToFile:tmpfilePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
- 保存到文件夹目录下
NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *testDirectory = [cachePath stringByAppendingPathComponent:@"test"];
// 创建目录
BOOL res=[fileManager createDirectoryAtPath:testDirectory withIntermediateDirectories:YES attributes:nil error:nil];
if (res) {
NSLog(@"文件夹创建成功");
}else
NSLog(@"文件夹创建失败");
//保存到文件test夹下边
NSString *cacheFilePath2 = [testDirectory stringByAppendingPathComponent:@"cache.txt"];
[str writeToFile:cacheFilePath2 atomically:YES encoding:NSUTF8StringEncoding error:nil];
NSLog(@"cache:%@",cacheFilePath2);
其他文件夹下 小结:这里可以得出write写入方式,是覆盖式写入
第二部分:基础保存数据方式
了解沙盒的相关内容之后,更加方便我们进行数据存储的操作.
" 谈到数据储存,首先要明确区分两个概念,数据结构和储存方式。所谓数据结构就是数据存在的形式。除了基本的NSDictionary、NSArray和NSSet这些对象,还有更复杂的如:关系模型、对象图和属性列表多种结构。而存储方式则简单的分为两种:内存与闪存。内存存储是临时的,运行时有效的,但效率高,而闪存则是一种持久化存储,但产生I/O消耗,效率相对低。把内存数据转移到闪存中进行持久化的操作称成为归档。"
---引自《对比iOS中的四种数据存储》
iOS中,我们常见的四种方式分别为:
- plist 储存
- write 文件写入
- NSKeyedArchiver 归档(序列化)
- NSUserDefaults 偏好保存
其他SQLite,CoreData我之前有写过,有需要的朋友移步到这里,博客下还有其他相关文章
四种保存方式分析
plist储存:
list本身就是XML文件.
plist主要保存的数据类型为NSString、NSNumber、NSData、NSArray、NSDictionary等,不能存储自定义对象
write:
永久保存在磁盘中
需要指定保存文件的目录路径
NSUserDefaults:
NSUserDefaults实质就是plist,我们可以在沙盒目录下看到起保存的文件就是一个.plist文件
NSUserDefaults 是一个单例对象,在整个应用程序的生命周期中都只有一个实例。
NSUserDefaults保存的数据类型有:NSNumber, float,double,CGFloat基本数据类型, NSString, NSData, NSArray, NSDictionary等. 其他不同格式的数据,需要转化成对应的
NSUserDefaults一般保存配置信息,比如用户名、密码、是否保存用户名和密码或者一些个人设置中的配置信息。
NSKeyedArchiver:
需要在实体类中实现NSCoding代理(动态归档解档实体属性,可以移步这里), 实现encodeWithCoder:和initWithCoder:两个归解档方法
写入文件是什么格式,读取的时候就直接是什么格式.
相关代码
plist:
NSString *st2r = @"7777777777777777777777";
NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
NSLog(@"%@",cachePath);
NSString *filePath = [cachePath stringByAppendingPathComponent:@"dict.plist"]
- 读取:
NSString *dict = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
- write:
如上
NSKeyedArchiver:
- 写入:
//1.创建对象
Person *p=[[Person alloc]init];
p.name=@"2222222";
p.age=1111111;
//2.获取文件路径
NSString *docPath=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
NSString *path=[docPath stringByAppendingPathComponent:@"person22222.person"];
NSLog(@"path=%@",path);
//3.将自定义的对象保存到文件中
[NSKeyedArchiver archiveRootObject:p toFile:path];
- 读取:
Person *p = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
NSUserDefaults:
- 写入:
[[NSUserDefaults standardUserDefaults] setObject:<#(nullable id)#> forKey:<#(nonnull NSString *)#>];
- 读取:
[[NSUserDefaults standardUserDefaults] objectForKey:<#(nonnull NSString *)#>];
推荐文章如下:
《 iOS学习之iOS沙盒(sandbox)机制和文件操作(一)》
交流
希望能和大家交流技术
我的博客地址: http://www.lilongcnc.cc/