file system

ios的文件管理有1.属性列表2.归档3.数据库(SQLite)4.coreData4种方式

属性列表Plist

IPA的存储空间

沙盒 Sandbox :读可写

1
NSString *docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;

应用程序文件 Bundle :只读

1
NSString *settingPath = [[NSBundle mainBundle] pathForResource:@"Setting" ofType:@"plist"];

手动创建plist文件

info.Plist

系统plist文件

通过对应的key获取info.plist中的信息

如版本号versio

1
2
NSDictionary *infoDic = [[NSBundle mainBundle] infoDictionary];
NSString *versionNumber = infoDic[versionKey];

配置一个自定义plist

  1. 首次运行时,需要有一个默认的配置文件plist(模板,通常是bundle中的plist)
  2. 因为用户要能够修改配置,bundle中的文件是只读, 所以要把bundle中的模板写到Documents文件夹下

流程

  1. 创建一个模板(plist)
  2. 运行时检查是否复制过模板到Documents下,没复制过 就复制一份
  3. 设置页面显示时,读取Documents目录下的模板,把相关设置显示在界面上
  4. 当用户更改设置时,同步修改对应模板

系统自动创建plist:NSUserDefaults

  • 本质上就是一个plist文不过是系统提供的.
  • 存储的位置在沙盒(SandBox) ~/Library/Preferences/

只有当我们添加过值(setObject)以后,这个文件才会自动生成

1
2
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:@"小明" forKey:@"name"];

额外的提供了向系统plist中存非对象类型的方法

1
2
[userDefaults setInteger:12 forKey:@"age"];
[userDefaults setBool:YES forKey:@"Marry"];

文件的写入,是在每个runloop时进行,我们可以手动调用保存的方法,防止系统以外崩溃而导致没有存储的情况发生

1
[userDefaults synchronize];

归档Archive

归档/解档 : 压缩+解压缩
把对象类型存到磁盘中的统一解决方案

被归档对象需要遵循 NSCoding协议

通过协议方法对被归档对象编码解码

对被归档对象编码

[aCoder encodeObject:self.name forKey:@”name”];

对被归档对象解码

self.name = [aDecoder decodeObjectForKey:@”name”];

归档操作

archiveRootObject

1
BOOL isSucessed = [NSKeyedArchiver archiveRootObject:stu toFile:self.archivePath];

解档操作

unarchiveObjectWithFile

1
Student *stu = [NSKeyedUnarchiver unarchiveObjectWithFile:self.archivePath];

RUNTIME类简化对象归档时的编码解码操作

1
2
3
4
5
6
7
8
9
10
11
-(void)func{
unsigned int outCount = 0;
Ivar *varList = class_copyIvarList(self.class,&outCount);
//参数1:要获取的属性列表所在的class类
//参数2:二级指针,回传属性的数量
//返回值:所有属性列表,不包含父类的
const char *name = ivar_getName(tmpIvar);
//从Ivar构造体中获取属性名字符串
free(varList);
//varList用完必须释放,c语言没有自动释放
}

示例:将运用runtime的编码解码代码做成宏定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
- (void)encodeWithCoder:(NSCoder *)aCoder{
//1.获取属性列表
unsigned int outCount = 0;
Ivar *varList = class_copyIvarList(self.class, &outCount);
//2.通过for循环,对每个属性进行设置
for (int i = 0; i< outCount; i++) {
//Ivar是结构体,包含属性名等..
Ivar tmpIvar = varList[i];
//从Ivar构造体中获取属性名字符串
const char *name = ivar_getName(tmpIvar);
//C字符串->OC字符串
//3.获取属性的名称的字符串
NSString *propertyName = [NSString stringWithUTF8String:name];
NSLog(@"propertyName %@", propertyName);
//KVC
id obj = [self valueForKey:propertyName];
//4.通过KVC模式,获取对应的值
[aCoder encodeObject:obj forKey:propertyName];
}
free(varList);
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder{
if (self = [super init]) {
//1.拿属性列表
unsigned int outCount = 0;
Ivar *varList = class_copyIvarList(self.class, &outCount);
for (int i = 0; i < outCount; i++) {
Ivar tmpVar = varList[i];
const char *name = ivar_getName(tmpVar);
NSString *propertyName = [NSString stringWithUTF8String:name];
//从压缩包(aDecoder)中根据key解压缩出值
id obj = [aDecoder decodeObjectForKey:propertyName];
[self setValue:obj forKey:propertyName];
}
free(varList);
}
return self;
}

数据库

CoreData