沙盒 & 本地持久化方案

1、沙盒

iOS程序默认情况下只能访问程序自己的目录,这个目录被称为“沙盒”。

沙盒的目录结构:

1
2
3
4
5
6
"应用程序包"
- Documents
- Library
*Caches
*Preferences
- tmp

1.1.”应用程序包”:

这里存放的是应用程序的源文件,包括资源文件和可执行文件。

1
2
String *path = [[NSBundle mainBundle] bundlePath];
NSLog(@"%@", path);

1.2.Documents:

最常用的目录,iTunes同步该应用时会同步此文件夹中的内容,适合存储重要数据。

1
2
3
4
5
6
NSString *path = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory,
NSUserDomainMask,
YES).firstObject;

NSLog(@"%@",path);

1.3.Library/Caches:

iTunes不会同步此文件夹,适合存储体积大,不需要备份的非重要数据。

1
2
3
4
5
NSString *path = NSSearchPathForDirectoriesInDomains(
NSCachesDirectory,
NSUserDomainMask, YES).firstObject;

NSLog(@"%@",path);

1.4.Library/Preferences:

iTunes同步该应用时会同步此文件夹中的内容,通常保存应用的设置信息。

1.5.tmp:

iTunes不会同步此文件夹,系统可能在应用没运行时就删除该目录下的文件,所以此目录适合保存应用中的一些临时文件,用完就删除。

1
2
NSString *path = NSTemporaryDirectory();
NSLog(@"%@", path);

2、本地持久化方案

2.1.plist文件

通过XML文件的方式保存数据,支持保存的数据类型有:

  1. NSArray;
  2. NSMutableArray;
  3. NSDictionary;
  4. NSMutableDictionary;
  5. NSData;
  6. NSMutableData;
  7. NSString;
  8. NSMutableString;
  9. NSNumber;
  10. NSDate;

plist读写数据示例:

1
2
3
4
5
6
7
8
9
10
NSString *path = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory,NSUserDomainMask,YES).firstObject;

NSString *fileName = [path stringByAppendingPathComponent:@"nameXX.plist"];

NSArray *array = @[@"1", @"2", @"3"];
[array writeToFile:fileName atomically:YES];

NSArray *result = [NSArray arrayWithContentsOfFile:fileName];
NSLog(@"%@", result);

2.2.KeyChain 钥匙串

信息存储到钥匙串中之后,在应用删除重新安装时,仍然能取出之前保存的值。可以使用第三方库UICKeyChainStore实现钥匙串存储操作(Github地址)。

2.3.preference(偏好设置)

用来保存应用程序的配置信息的。如果需要立即写入文件的就必须调用synchronize方法,否则系统会根据I/O情况不定时刻地保存到文件中。

1
2
3
4
5
6
7
8
9
10
//1.获得NSUserDefaults文件
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
//2.向文件中写入内容
[userDefaults setObject:@"AAA" forKey:@"a"];
//2.1立即同步
[userDefaults synchronize];

//3.读取文件
NSString *name = [userDefaults objectForKey:@"a"];
NSLog(@"%@", name);

2.4.NSKeyedArchiver(归档)

归档,只要遵循了 NSCoding 协议的对象都可以通过它实现序列化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@interface Person : NSObject <NSCoding>

@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;

@end

@implementation Person
//解档
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
if ([super init]) {
self.name = [aDecoder decodeObjectForKey:@"name"];
self.age = [aDecoder decodeIntegerForKey:@"age"];
}
return self;
}
//归档
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeInteger:self.age forKey:@"age"];
}
@end

存取示例:

1
2
3
4
5
6
7
8
9
10
11
NSString *file = [NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES).firstObject
stringByAppendingPathComponent:@"person.data"];
//存
Person *person = [[Person alloc] init];
person.name = @"III";
person.age = 20;
[NSKeyedArchiver archiveRootObject:person toFile:file];
//取
Person *newPerson = [NSKeyedUnarchiver unarchiveObjectWithFile:file];
NSLog(@"++++%@",newPerson.name);

如果需要归档的类是某个自定义类的子类时,就需要在归档和解档之前先实现父类的归档和解档方法。即 [super encodeWithCoder:aCoder] 和 [super initWithCoder:aDecoder] 方法;

2.5.CoreData

未完待续。。


沙盒 & 本地持久化方案
https://davidlii.cn/2017/12/05/sandbox.html
作者
Davidli
发布于
2017年12月5日
许可协议