沙箱模型的有四个文件夹
documents,tmp,app,Library。
四个文件夹分别是什么
Documents 目录:您应该将所有de应用程序数据文件写入到这个目录下。这个目录用于存储用户数据或其它应该定期备份的信息。
tmp 目录:这个目录用于存放临时文件,保存应用程序再次启动过程中不需要的信息。
AppName.app 目录:这是应用程序的程序包目录,包含应用程序的本身。由于应用程序必须经过签名,所以您在运行时不能对这个目录中的内容进行修改,否则可能会使应用程序无法启动。
Library 目录:这个目录下有两个子目录:Caches 和 Preferences
Library/Preferences 目录:包含应用程序的偏好设置文件。您不应该直接创建偏好设置文件,而是应该使用NSUserDefaults类来取得和设置应用程序的偏好.(利用NSUserDefaults存储的数据就是在沙盒中的这个文件夹中)
Library/Caches 目录:用于存放应用程序专用的支持文件,保存应用程序再次启动过程中需要的信息。
沙盒中各个目录的路径获取方式
1.获取沙盒中home目录(主目录,沙盒的最外层)的路径
NSString *homeDir = NSHomeDirectory();
NSLog(@"获取沙盒中home目录路径\n %@",homeDir);
打印结果
2016-06-17 21:12:06.264 sd[9698:422028] 获取沙盒中home目录路径
/Users/zhangbin/Library/Developer/CoreSimulator/Devices/46A6D7C4-D373-4684-A640-4B4A1FF2BC6E/data/Containers/Data/Application/5E081742-A012-48E6-B70A-77906491B714
2.获取沙盒中Documents目录的路径
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [paths objectAtIndex:0];
NSLog(@"获取沙盒中Documents目录的路径\n %@",docDir);
打印结果:
2016-06-17 21:12:06.264 sd[9698:422028] 获取沙盒中Documents目录的路径
/Users/zhangbin/Library/Developer/CoreSimulator/Devices/46A6D7C4-D373-4684-A640-4B4A1FF2BC6E/data/Containers/Data/Application/5E081742-A012-48E6-B70A-77906491B714/Documents
3.获取沙盒中Caches目录的路径
NSArray *path2 = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cachesDir = [path2 objectAtIndex:0];
NSLog(@"获取沙盒中Caches目录的路径\n %@",cachesDir);
打印结果:
2016-06-17 21:12:06.264 sd[9698:422028] 获取沙盒中Caches目录的路径
/Users/zhangbin/Library/Developer/CoreSimulator/Devices/46A6D7C4-D373-4684-A640-4B4A1FF2BC6E/data/Containers/Data/Application/5E081742-A012-48E6-B70A-77906491B714/Library/Caches
4.获取沙盒中tmp目录的路
NSString *tmpDir = NSTemporaryDirectory();
NSLog(@"获取沙盒中tmp目录的路径\n %@",tmpDir);
打印结果:
2016-06-17 21:12:06.265 sd[9698:422028] 获取沙盒中tmp目录的路径
/Users/zhangbin/Library/Developer/CoreSimulator/Devices/46A6D7C4-D373-4684-A640-4B4A1FF2BC6E/data/Containers/Data/Application/5E081742-A012-48E6-B70A-77906491B714/tmp/
NSUserDefaults详细介绍
- 1.NSUserDefaults类用于保存应用程序设置和属性以及用户数据。例如,你可以存储用户在应用程序中使用的图片或默认颜色方案,或者背景等。这些对象存储在iOS所谓的“defaults系统”中。
- 2.iOS的defaults系统在整个app中都是可用的,因此存放到defaults系统中的数据也是整个应用程序生命周期中可用的。也就是说,无论用户关闭程序还是关机,在用户再次打开程序或开机后这些数据仍然存在。
- 3.从NSUserDefaults返回的值是不可改变的,即便是你在存储的时候使用的是可变的值。例如你使用mutable string做为“MyStringDefault”的值,当你做使用stringForKey:方法获取的值,这个值仍然是不可变的。
- 4.NSUserDefaults是单例,同时也是线程安全的
-
5.NSUserDefaults可以存储的数据类型只能是property list类型的数据。(NSData,NSString,NSNumber,NSDate,NSArray,NSDictionary)
如果你想保存其他类型,如UIImage,你应该进行编码(即archive),或者将它转换为NSData、NSNumber或者NSString。 -
6.[NSUserDefaults standardUserDefaults]用来记录一下永久保留的数据非常方便,不需要读写文件,而是保留到一个NSDictionary字典里,由系统保存到文件里,系统会保存到该应用下的/Library/Preferences/gongcheng.plist文件中。需要注意的是如果程序意外退出,NSUserDefaultsstandardUserDefaults数据不会被系统写入到该文件,不过可以使用[[NSUserDefaultsstandardUserDefaults] synchronize]命令直接同步到文件里,来避免数据的丢失。
-
手动保存的文件在documents文件里,Nsuserdefaults保存的文件在Library/Preferences 目录文件夹里;
NSUserDefaults六大方法:
一.得到共享的NSUserDefaults实例
+ (NSUserDefaults *)standardUserDefaults
二.初始化一个NSUserDefaults对象
- (id)initWithUser:(NSString *)username
三.得到默默认值
- objectForKey:;
- stringForKey:;
- arrayForKey:;
- dictionaryForKey:;
- dataForKey:;
- stringArrayForKey:;
- integerForKey:;
- floatForKey:;
- doubleForKey:;
- boolForKey:;
- URLForKey:;
四.设置默认值
- setInteger:forKey:;
- setFloat:forKey:;
- setDouble:forKey:;
- setBool:forKey:;
- setURL:forKey:;
五.记录默认值
- registerDefaults:;
六.删除默认值
- removeObjectForKey:;
如何使用NSUserDefaults?
你可以把它当做是一个小型的数据库,在存储和读取数据之前,你需要调用方法: standardUserDefaults :
如:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
我把这个方法理解为,打开数据库的大门,这样你就可以对里面的数据做各种操作,也可以将存储数据进来。
存储数据和读取数据有各种方法,需要注意的是,存储数据需要完成方法 synchronize:,这个方法完成的作用是同步数据,也就是将你做出改变的数据更新。
如:
[defaults synchronize];
NSUserDefaults具体用法
-
IOS提供了一个轻量级的快速数据存储方式:NSUserDefaults,对于SQLite这样的数据库方式,适合大量数据的存储。
-
程序运行的时候从用户默认的数据库中读取程序的设置,同时NSUserDefaults的缓存避免了在每次读取数据时候都打开用户默认数据库的操作,所有数据都放在内存中,读写速度很快。
1.获取 NSUserDefaults
这是一个单例,获取非常方便,随时可以调用:
[NSUserDefaults standardUserDefaults];
2.写入数据到NSUserDefaults中
[[NSUserDefaults standardUserDefaults] setInteger:10 forKey:@"test"];
[[NSUserDefaults standardUserDefaults] setFloat:10.0 forKey:@"test"];
..... NSUserDefaults 支持多种数据类型,用 key来标示
3.读取NSUserDefaults中存储的数据
int a = [[NSUserDefaults standardUserDefaults] integerForKey:@"test"];
float a = [[NSUserDefaults standardUserDefaults] floatForKey:@"test"];
。。。当然也支持其他各种类型
4.保存数据,实现持久化存储
[[NSUserDefaults standardUserDefaults] synchronize];
5.判断数据是否存在
if([[NSUserDefaults standardUserDefaults] objectForKey:@""test"]==nil){
......
}else{
......
}
NSUserDefaults和Property List(属性表,也就是plist文件)区别
- Property List (属性表)
- 定义:Property List文件是一种用来存储序列化后的对象 的文件。属性列表文件的文件扩展名 为.plist,因此通常被称为 plist 文件。
- pl是一种格式,包含了(NSData,NSString,NSNumber,NSDate,NSArray,NSDictionary 这六种任意组合创建的结构体)
- NSUserDafults
- NSUserDafults相当于一个缓存,而plist是一个文件。
- NSUserDefault,它其实也是以property list 的形式来存储的,但是它有限制,比如说NSColor和NSFont等类型式不能够直接存储的,我们必须要转换他们,要把他们转换成NSData类型来存。
如何获取利用NSUserDefaults存储数据的路径?
- 1.先获取沙盒中home目录(主目录,沙盒的最外层)的路径
NSString *homeDir = NSHomeDirectory();
NSLog(@"获取沙盒中home目录路径\n %@",homeDir);
- 2.然后找到Library/Preferences这个目录,这个目录下的plist文件就是数据的最终路径
iOS中数据存储方式
- 方式1.Plist(利用writeToFile/arrayWithContentsOfFile)
// 向plist文件中存数据
NSArray *data = @[@"Marry",@"Lucy"];
[data writeToFile:@"/Users/zhangbin/Desktop/zhangbin.plist" atomically:YES];
// 再次向这个plist文件中存数据时,首先必须得取出这个plist中的数据,然后再添加数据,最后才可以写入到plist文件
NSMutableArray *data = [NSMutableArray arrayWithContentsOfFile:@"/Users/zhangbin/Desktop/zhangbin.plist"];
[data addObject:@"Tom"];
[data writeToFile:@"/Users/zhangbin/Desktop/zhangbin.plist" atomically:YES];
精华demo
#import "ViewController.h"
@interface ViewController ()
@property(nonatomic,strong)NSDictionary *Dic;
@property(nonatomic,strong)NSMutableDictionary *sectionDic;
@end
@implementation ViewController
-(NSDictionary *)Dic{
if(_Dic == nil){
_Dic = [NSDictionary dictionary];
}
return _Dic;
}
-(NSMutableDictionary *)sectionDic{
if(_sectionDic == nil){
_sectionDic = [NSMutableDictionary dictionary];
}
return _sectionDic;
}
// 例2:复杂测试
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableArray * sectionArr = [[NSMutableArray alloc] init];
NSMutableDictionary * rowDic = [[NSMutableDictionary alloc] init];
for (int i = 0; i < 2; i ++) {
for (int j = 0; j < 4; j ++) {
[rowDic setObject:@"NO" forKey:@"selected"];// 等价rowDic[@"selected"]=@"NO";
[sectionArr addObject:rowDic];
}
// 总结:key不能为NSNumber,key只能为字符串。 value可以为字符串,也可以为NSNumber
// [self.sectionDic setObject:sectionArr forKey:@(i)];// 错误写法
// 正确写法
[self.sectionDic setObject:sectionArr forKey:[NSString stringWithFormat:@"%zd",i]];// 等价 self.sectionDic[ [NSString stringWithFormat:@"%zd",i]] = sectionArr;
}
/*****************************写plist文件到本地路径*****************************/
BOOL a = [self.sectionDic writeToFile:@"/Users/zhangbin/Desktop/Company/zb6.plist" atomically:YES];
if (a == 1) {
NSLog(@"写入成功");
}else{
NSLog(@"写入失败");
}
NSLog(@"%@",self.sectionDic);
/*****************************写plist文件到沙盒********************************/
// 获取沙盒中Documents目录的路径
NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *plistPath1 = [paths objectAtIndex:0];
//拼接plist文件,得到完整的文件名
NSString *filename = [plistPath1 stringByAppendingPathComponent:@"CoderZb.plist"];
// 打印plist文件的总路径
NSLog(@"%@",filename);
[self.sectionDic writeToFile:filename atomically:YES];
// 打印读取plist文件
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:filename];
// 打印plist文件中的内容
NSLog(@"%@",dict);
}
// 例1:简单测试
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
// 总结:key不能为NSNumber,key只能为字符串。 value可以为字符串,也可以为NSNumber
// NSDictionary *dict3=@{@"a":@"b",@"c":@"d"};// 写入成功
// NSDictionary *dict3=@{@(1):@"b",@"c":@"d"};// 写入失败
NSDictionary *dict3=@{@"a":@(2),@"c":@"d"};// 写入成功
[dict3 writeToFile:@"/Users/zhangbin/Desktop/Company/zhangbin.plist" atomically:YES];
}
@end
打印。.png
写入到plist文件.png
- 方式2.Preference(利用NSUserDefaults取得和设置应用程序的偏好.)
// 将NSString 对象存储到 NSUserDefaults 中
NSString *passWord = @"1234567";
NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
[user setObject:passWord forKey:@"userPassWord"];
// 从NSUserDefaults中取出数据,只需要取出key 对应的值就好了
NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
NSString *passWord = [ user objectForKey:@"userPassWord"];
- 方式3.NSCoding(利用NSKeyedArchiver\NSkeyedUnarchiver)
/************toFile和unarchiveObjectWithFile的参数为字符串类型的路径*********************/
NSDictionary *glossary = [NSDictionary dictionaryWithObjectsAndKeys:@"A",@"B", @"C",@"D",nil];
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"glossary.archive"];
// 归档时,toFiled的参数写成路径。解档时,objectForKey的参数也必须写成路径
// 使用NSKeyedArchiver归档
[NSKeyedArchiver archiveRootObject:glossary toFile:path];
NSLog(@"%@",path);
// 使用NSKeyedUnarchiver解档
NSDictionary *readglossary = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
for(NSString *key in readglossary){
NSLog(@"%@: %@",key,[readglossary objectForKey:key]);
}
/************toFile和unarchiveObjectWithFile的参数仅仅是普通的字符串*********************/
// dictionaryWithObjectsAndKeys的参数特殊,从冒号开始,@"A"为键,@"B"为值,以此类推
NSDictionary *glossary = [NSDictionary dictionaryWithObjectsAndKeys:@"A",@"B", @"C",@"D",nil];
// 归档时,toFiled的参数写成字符串.那么解档时,objectForKey的参数也必须写成字符串
[NSKeyedArchiver archiveRootObject:glossary toFile:@"glossary.archive"];
// 将文件glossary.archive中的数据读到字典对象并显示出来
NSDictionary *readglossary = [NSKeyedUnarchiver unarchiveObjectWithFile:@"glossary.archive"];
for(NSString *key in readglossary){
NSLog(@"%@: %@",key,[readglossary objectForKey:key]);
}
方式3打印结果:
2016-06-17 20:09:12.430 1[7975:345839] B: A
2016-06-17 20:09:12.432 1[7975:345839] D: C
2016-06-17 20:09:12.432 1[7975:345839] E: E
- 方式4.SQLite3(SQLite的第三个版本)
SQLite3是数据库技术,纯C语言版本,是轻量级
- 方式5.Core Data(苹果原声的数据存储方式)
Core Data是数据库技术,以SQLite3为基础的OC版本,且是重量级
-
各个方式的优缺点:
-
1.方式1和方式2只能存简单的数据类型的对象,例如存NSArray,NSDictionary.方式1和方式2都是存储成plist文件,所以这两种方式本质是一样的
-
2.方式3只要遵守NSCoding协议,并实现方法,就能够将任何类型的对象存入沙盒
-
3.方式和方式2和方式3都只能存小数据,不能存大数据
-
4.存大数据必须利用数据库也就是利用方式4或者方式5.因为利用数据库检索数据非常快,如果你想从数据库的1000个数据里面取出100和150之间的数据,不用读取全部的1000个数据,仅仅利用命令即可快速检索到。如果不利用数据库,而是利用方式1,方式2,方式3,必须得先把1000个数据读取出来,然后再截串,速度非常慢。
-
5.对于大批量的数据,我们要对这些数据做缓存的话,不能用Plist、Preference、NSCoding做缓存,应该用SQLite3或者Core Data来做缓存.如果是做小批量的数据,我们用Plist、Preference、NSCoding当中的哪一个做缓存都行
-
注意:无论采取了什么方式,其实都是把数据存储到文件中了,只是这个文件的类型决定了能存大数据还是小数据,没有什么可深奥的。因为文件的类型只有用对应的软件开,例如 sqlite后缀的文件只能用navicat打开,navicat是一款数据库管理工具。所以一般我们说将数据存到数据库中(不好理解),换句话说就是将数据存到了sqlite后缀的文件中(好理解)
数据库
-
数据库就是存储和管理数据的仓库
-
SQLite是轻量级的嵌入式数据库(非常的轻),一般用于Android、iPhone手机上,在设备中,SQLite只占用几百K的内存,处理速度比Mysql数据库块
-
数据库分为关系型数据库(主流)、对象型数据库
-
常用的关系型数据库:
-
1.PC端:Oracle、Mysql、SQLServer、Access、DB2、Sybase
-
2.移动客户端:SQLite
-
使用sqlite3报错的解决办法
92-01.png
归档、解档
92-05.png 92-06.png
注意归档\解档 和 对象转成NSData数据\将NSData数据转成对象的区别
- 归档
[NSKeyedArchiver archiveRootObject:shops toFile:@"/Users/apple/Desktop/shops.data"];
- 解档
NSMutableArray *shops = [NSKeyedUnarchiver unarchiveObjectWithFile:@"/user/xxx"];
- 对象shop转成NSData数据
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:shop];
- 将NSData数据转成对象shop
ZBShop *shop = [NSKeyedUnarchiver unarchiveObjectWithData:data];
用SDWebImage清除图片缓存功能
- 清除原理就是:因为用户浏览的缓存图片默认会存到沙盒中的Library中的Caches目录下,所以SDWebImage框架底层会找到沙盒的Library中的Caches目录下的图片缓存,删除缓存在这里面的图片。没啥难的,就是找到缓存文件,删除即可
- 验证:
- 步骤1:在程序中输入如下代码
NSArray *path2 = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cachesDir = [path2 objectAtIndex:0];
NSLog(@"获取沙盒中Caches目录的路径\n %@",cachesDir);
-
步骤2:浏览程序中的图片
-
步骤3:复制步骤1中打印出来的路径,查找路径的位置
-
步骤4:点击清除按钮,执行SDWebImage清除缓存的代码,看里面的文件是否消失,如果消失了,可以验证确实清除了缓存的图片。
-
步骤5:如果还不放心,可以在缓存路径的目录下,手动粘贴几张图片,几个文件夹等等,然后你再点击清除按钮,发现也能删除这些手动粘贴的数据
-
步骤6:附动态截图
封装一个分类:根据文件夹路径,计算文件夹的大小
-
利用NSFileManager,可以获取文件夹,从而操纵这个文件夹,你可以删除这个文件夹中的内容
-
系统底层不能够计算文件夹的大小,只能计算文件的大小,因为文件夹没有大小属性,文件才有大小属性,所以如果我们想要得到文件夹的大小,如何做呢?
- 答: 利用NSFileManager遍历出这个文件夹中的文件,将遍历出的每个文件的大小相加,从而间接的得到文件夹的大小
-
想要永久的将图片数据放入缓存中,必须放在沙盒的Library的Caches文件中,不要放在temp(临时的文件夹,系统随机删除),也不要放在Documents中,放在Documents中时候,你请求苹果审核你的app时,会被拒的,原因就是不能再Documents中放下载的缓存图片
利用SDWebImage清除图片缓存和利用NSFileManager清除图片缓存
1.利用SDWebImage清除图片缓存.
[[SDImageCache sharedImageCache] clearDisk];
2.利用NSFileManager清除图片缓存
NSFileManager *mgr = [NSFileManager defaultManager];
// 缓存路径
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
// 删除removeItemAtPath参数中的Caches目录下的文件
[mgr removeItemAtPath:caches error:nil];
总结:
-
1和2本质是一样的,因为图片缓存就是在Caches目录下的,1的底层就是通过删除Caches目录下的图片来解决图片缓存的问题,只不过没有将缓存路径暴露在外面罢了。1只能删除存在Caches目录下的图片,不能删除存在tmp目录下的视频、音频文件。
-
2是系统自带的NSFileManager类,我们仅仅用了它其中的一个小小的功能解决图片缓存问题的,因为removeItemAtPath的参数代表的路径是Caches路径,所以实现了删除Caches目录下的图片来解决图片缓存的问题
-
2的功能局限,清除缓存的话,只能清除存储在Caches目录下的图片缓存,2的功能强大,能删除任何路径下的缓存,但是你必须先告诉NSFileManager类,指定删除哪个路径中的文件
图片缓存和视频、音频缓存默认的存储路径
- 图片缓存存储在沙盒的Library/Caches目录下,如果我们没有做删除操作,图片缓存就一直存在
- 视频、音频存储在沙盒的tmp/MediaCache目录下,我们不需要做删除操作,tmp目录下的文件也会随时删除
网友评论