写在前面:
iOS沙盒机制, 随便百度一下就有很多很多文章, 这篇也没什么新的东西. 只是看千篇文章都不如自己总结一次来得记忆深刻.
1. iOS沙盒机制介绍
- iOS应用程序只能在为该改程序创建的文件系统中读取文件,不可以去其它地方访问,此区域被成为沙盒;
- 所有的非代码文件都要保存在沙盒中,例如图像,图标,声音,映像,属性列表,文本文件等;
2. 沙盒文件夹目录结构
- iOS每个应用程序都有自己的三个目录(Document,Library,tmp),他们之间不能相互访问;
- /MyApp.app:
①存放内容
该目录包含了应用程序本身的数据,包括资源文件和可执行文件等。程序启动以后,会根据需要从该目录中动态加载代码或资源到内存,这里用到了lazy loading的思想。
②整个目录是只读的
为了防止被篡改,应用在安装的时候会将该目录签名。非越狱情况下,该目录中内容是无法更改的;在越狱设备上如果更改了目录内容,对应的签名就会被改变,这种情况下苹果官网描述的后果是应用程序将无法启动,我没实践过。
③是否会被iTunes同步
否
/Document:存放应用程序的数据 (苹果建议将程序中建立的或在程序中浏览到的文件数据保存在该目录下,iTunes备份和恢复的时候会包括此目录);
-
/Library:存储程序的默认设置或其它状态信息
- 子文件夹有Caches, Preferences
- /Caches: 保存用户使用应用程序时产生的缓存文件, 比如网络请求的数据. 应用程序通常还需要负责删除这些文件. 不会被iTunes同步;
- /Preferences: 应用程序的偏好设置文件. 我们使用NSUserDefaults写的设置数据都会保存到该目录下的一个plist文件中,这就是所谓的写入plist中. 会被iTunes同步;
tmp:应用程序存储的临时文件(应用程序再次启动时不需要的文件). 比如系统磁盘存储空间不足的时候, 该目录下的文件随时有可能被系统清理掉.不会被iTunes同步.
3. 获取沙盒各个文件夹路径
- 沙盒根目录
NSLog(@"%@",NSHomeDirectory());'
- MyApp.app
NSLog(@"%@",[[NSBundle mainBundle] bundlePath]);
- /Documents
// 参数1: 要查找的目录
// 参数2: 是否是用户主目录
// 参数3: YES/NO 是否获取全路径.
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentPath = [paths lastObject];
NSLog(@"%@", documentPath);
这里用到的NSSearchPathForDirectoriesInDomains方法需要解释下,其声明如下:
FOUNDATION_EXPORT NSArray *NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask, BOOL expandTilde);
该方法用于返回指定范围内的指定名称的目录的路径集合。有三个参数:
- directory
NSSearchPathDirectory类型的enum值,表明我们要搜索的目录名称,比如这里用NSDocumentDirectory表明我们要搜索的是Documents目录。如果我们将其换成NSCachesDirectory就表示我们搜索的是Library/Caches目录。- domainMask
NSSearchPathDomainMask类型的enum值,指定搜索范围,这里的NSUserDomainMask表示搜索的范围限制于当前应用的沙盒目录。还可以写成NSLocalDomainMask(表示/Library)、NSNetworkDomainMask(表示/Network)等。- expandTilde
BOOL值,表示是否展开波浪线。我们知道在iOS中的全写形式是/User/userName,该值为YES即表示写成全写形式,为NO就表示直接写成“~”。
- /Library
//获取Library目录
NSArray * paths2 = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString * libraryPath = [paths2 lastObject];
NSLog(@"%@", libraryPath);
- /Library/Caches
//获取cache目录
NSArray * paths3 = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString * cachePath = [paths3 lastObject];
NSLog(@"%@", cachePath);
- /Library/Preference
//获取Preference目录
// 注意: Preferences 只能用拼接的方式找到,NSPreferencePanesDirectory 只能找到PreferencePanes
// PreferencePanes iphone 并没有这个目录.
NSArray * paths4 = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString * preferencePath = [[paths4 lastObject] stringByAppendingPathComponent:@"Preferences"];
NSLog(@"%@", preferencePath);
- /Tmp
NSLog(@"%@",NSTemporaryDirectory()); // tmp文件夹路径
4. 沙盒实现数据的持久化存储
- 存入Preference(偏好设置)
- 存储
//1.获得NSUserDefaults文件
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
//2.向文件中写入内容
[userDefaults setObject:@"AAA" forKey:@"a"];
[userDefaults setBool:YES forKey:@"sex"];
[userDefaults setInteger:21 forKey:@"age"];
//2.1立即同步
[userDefaults synchronize];
- 读取
NSString *name = [userDefaults objectForKey:@"a"];
BOOL sex = [userDefaults boolForKey:@"sex"];
NSInteger age = [userDefaults integerForKey:@"age"];
NSLog(@"%@, %d, %ld", name, sex, age);
- 使用注意
- 偏好设置是专门用来保存应用程序的配置信息的,一般不要在偏好设置中保存其他数据;
- 如果没有调用synchronize方法,系统会根据I/O情况不定时刻地保存到文件中。所以如果需要立即写入文件的就必须调用synchronize方法;
- 偏好设置会将所有数据保存到同一个文件中。即preference目录下的一个以此应用包名来命名的plist文件.
- 写入plist文件, 通过XML文件的方式保存在对应目录中(如/Documents)
- 存储
- 1.获取文件路径(假如是该App的文件数据, 要保存在/Documents目录下)
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
NSString *filePath = [path stringByAppendingPathComponent:@"123.plist"];
- 2.将数据写入以上路径的文件
NSArray *array = @[@"123", @"456", @"789"];
[array writeToFile:fileName atomically:YES];
- 读取
NSArray *result = [NSArray arrayWithContentsOfFile:fileName];
NSLog(@"%@", result);
- 使用注意
- 只有以下类型才能使用plist文件存储
NSArray;
NSMutableArray;
NSDictionary;
NSMutableDictionary;
NSData;
NSMutableData;
NSString;
NSMutableString;
NSNumber;
NSDate;
- 存储时使用writeToFile: atomically:方法。 其中atomically表示是否需要先写入一个辅助文件,再把辅助文件拷贝到目标文件地址。这是更安全的写入文件方法,一般都写YES;
参考文章:
http://www.jianshu.com/p/f74a5ef11b78
http://blog.csdn.net/iunion/article/details/46889073
http://www.cocoachina.com/ios/20150720/12610.html