何谓数据持久化?

能将内催中的数据类型转换为存储模型,并能在将来需要时将存储模型还原为数据模型的机制。通俗讲就是将数据包存在非一时性设备中,并能在需要的时候恢复,苹果也就是从内存到闪存的过程。

NSUserDefaults

用NSUserDefaults存储配置信息

NSUserDefaults本质是以Key-Value形式存在plist文件,放在App的Library/Preferences目录下。这个文件是不安全的,所以千万不要用NSUserDefaults来存储密码之类的敏感消息,用户名密码应该使用KeyChain来存储
NSUserDefaults被设计用来存储设备和应用的配置信息,它通过一个工厂方法返回默认的、也是最常用到的实例对象。这个对象中储存了系统中用户的配置信息,开发者可以通过这个实例对象对这些已有的信息进行修改,也可以按照自己的需求创建新的配置项。
/**
 1. 该单例对象封装了对plist文件的读写操作,可以对每个字段单独读写
 2. 该plist文件在系统的Library/Preferences目录下,名字为<<Bundle Identify.plist>>
 */
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

// 2. 写操作
// 将开关的值记录到plist文件中,键为"switch"
[defaults setBool:_toggle.on forKey:@"switch"];

// 将进度值文本框的内容记录到plist文件中,键为"progress"
NSString *progress = _progressTextField.text;
float progressValue = [progress floatValue];
[defaults setFloat:progressValue forKey:@"progress"];

// 将输入文本框的内容记录到plist文件中,键位"input"
[defaults setObject:_inputTextField.text forKey:@"input"];

// 3. 将内存中的配置值,刷新到plist文件中
[defaults synchronize];
NSUserDefaults把配置信息以字典的形式组织起来,支持字典的项包括:字符串或者是数组,除此之外还支持数字等基本格式。一句话概括就是:基础类型的小数据的字典。操作方法几乎与NSDictionary的操作方法无异,另外还可以通过指定返回类型的方法获取到指定类型的返回值。
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

_toggle.on = [defaults boolForKey:@"switch"];

_progressView.progress = [defaults floatForKey:@"progress"];

_label.text = [defaults stringForKey:@"input"];

SQLite

iOS的SDK里预置了SQLite的库,开发者可以自建SQLite数据库。SQLite每次写入数据都会产生IO消耗,把数据归档到相应的文件。

SQLite擅长处理的数据类型其实与NSUserDefaults差不多,也是基础类型的小数据,只是从组织形式上不同。开发者可以以关系型数据库的方式组织数据,使用SQL DML来管理数据。 一般来说应用中的格式化的文本类数据可以存放在数据库中,尤其是类似聊天记录、Timeline等这些具有条件查询和排序需求的数据。

每一个数据库的句柄都会在内存中都会被分配一段缓存,用于提高查询效率。另一个方面,由于查询缓存,当产生大量句柄或数据量较大时,会出现缓存过大,造成内存浪费。

SQLite的使用起来要比NSUserDefaults复杂的多,因此建议开发者使用SQLite要搭配一个操作控件使用,可以简化操作。

NSCoding+NSKeyedArchiver

1.NSCoding协议
// 解档 反序列化 解码 从data(file)->对象
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super init]) {
        _name = [aDecoder decodeObjectForKey:kNameKey];
        _age = [aDecoder decodeIntForKey:kAgeKey];
        _identify = [aDecoder decodeObjectForKey:kIdKey];
    }

    return self;
}

// 归档 序列化 编码 从对象->data(file)
- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:_name forKey:kNameKey];
    [aCoder encodeInt:_age forKey:kAgeKey];
    [aCoder encodeObject:_identify forKey:kIdKey];
}
2.保存数据
SFStudent *student = [[SFStudent alloc] init];
    student.name = _name.text;
    student.age = [_age.text intValue];
    student.identify = _identify.text;

    // 将student对象归档到文件
    [NSKeyedArchiver archiveRootObject:student toFile:_path];
3.读取数据
// 解档出一个对象
    SFStudent *student = [NSKeyedUnarchiver unarchiveObjectWithFile:_path];
    if (student == nil) {
        return;
    }

    _name.text = student.name;
    _age.text = [@(student.age) stringValue];
    _identify.text = student.identify;