【iOS】沙盒

沙盒(英语:sandbox,又译为沙箱),计算机专业术语,在计算机安全领域中是一种安全机制,为运行中的程序提供的隔离环境。

每个iOS应用都有自己的应用沙盒,iOS系统为每个应用程序创建自己的目录,每个应用程序只能访问自己的目录,不能直接通信。

iOS的沙盒文件系统根目录:

获取路径

每次编译运行都会生成一个新的沙盒路径,而真机不会生成新的沙盒。

获取沙盒根目录和tmp路径,系统提供了两个简易函数:
沙盒目录路径:

1
NSString *NSHomeDirectory(void);

tmp目录路径:

1
NSString *NSTemporaryDirectory(void);

iOS中获取沙盒目录下面指定文件夹路径有系统API提供支持

1
NSArray<NSString *> *NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask, BOOL expandTilde);
  • 这是一个返回值为数组的函数,一共有三个参数
    • directoryNSSearchPathDirectory枚举类型,iOS常用:
      • NSDocumentDirectory:Documents
      • NSLibraryDirectory:Library
      • NSCachesDirectory:Library/Caches
    • domainMaskNSSearchPathDomainMask枚举类型,iOS当前固定填写NSNetworkDomainMask
    • expandTilde:是否展开波浪号,iOS开发固定为YESNO是用在MacOS系统上的,因为一般只有PC才有破浪号~代表用户根路径。

由于返回值是一个数组,但一般情况下我们都会选择第一个元素,因为默认情况下只有一个元素。

Documents

保存应用运行时生成的需要持久化的数据,iTunes同步设备时会备份该目录。

获取Documents目录路径:

1
2
NSString *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
// 输出:/Users/Developer/Library/Developer/CoreSimulator/Devices/025F3833-218B-4695-B37F-135C289C6678/data/Containers/Data/Application/EACD6012-0638-49DF-B7D7-E7E6722F4D69/Documents

Library

Library里面包含两个文件夹(CachesPreferences

获取Library目录路径:

1
2
NSString *libraryPath = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES).firstObject;
// 输出:/Users/Developer/Library/Developer/CoreSimulator/Devices/025F3833-218B-4695-B37F-135C289C6678/data/Containers/Data/Application/EACD6012-0638-49DF-B7D7-E7E6722F4D69/Library

Caches

保存应用运行时生成的需要持久化的数据,iTunes同步设备时不会备份该目录。内存不足时会被清除,应用没有运行时,可能会被清除。一般存储体积大、不需要备份的非重要数据,比如图片、音视频等。

获取Caches目录路径:

1
2
NSString *cachesPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
// 输出:/Users/Developer/Library/Developer/CoreSimulator/Devices/025F3833-218B-4695-B37F-135C289C6678/data/Containers/Data/Application/EACD6012-0638-49DF-B7D7-E7E6722F4D69/Library/Caches

Preferences

保存应用的所有偏好设置,iTunes同步设备时会备份该目录。

NSUserDefaults默认存放在此文件夹

tmp

保存应用的运行时所需的临时数据,iTunes同步设备时不会备份该目录。应用使用完毕会清除该目录下的数据。

获取tmp目录路径:

1
2
NSString *tmp = NSTemporaryDirectory();
// 输出:/Users/Developer/Library/Developer/CoreSimulator/Devices/025F3833-218B-4695-B37F-135C289C6678/data/Containers/Data/Application/EACD6012-0638-49DF-B7D7-E7E6722F4D69/tmp/

探究NSUserDefaults存储方式

前面我们提到NSUserDefaults保存的数据默认存放在Library/Preferences。我们通过一个小案例看下。

创建两个按钮,分别做读写操作:

1
2
3
4
5
6
7
8
- (IBAction)writeAction {
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:@"idbeny" forKey:@"name"];
[userDefaults setBool:YES forKey:@"isHungry"];
[userDefaults setInteger:30 forKey:@"age"];

NSLog(@"%@", NSHomeDirectory());
}

进入沙盒,看到在Library/Perferences目录下生成了一个bundleId同名的plist文件

打开文件,查看数据,确实是刚才写入的数据

1
2
3
4
5
6
7
- (IBAction)readAction {
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSString *name = [userDefaults objectForKey:@"name"];
BOOL isHungry = [userDefaults boolForKey:@"isHungry"];
NSInteger age = [userDefaults integerForKey:@"age"];
NSLog(@"%@-%d-%ld", name, isHungry, age);
}

输出:idbeny-1-30

读取的和写入的数据一样,所以NSUserDefaults的本质就是一个字典类型的plist文件,文件名是bundleId,数据是以key-value的形式保存的。

注意:既然NSUserDefaults本质是一个plist文件,所以不能存储自定义对象,除非该对象实现NSCoding