什么是数据持久化?
概论
所谓的持久化,就是将数据保存到硬盘中,使得在应用程序或机器重启后可以继续访问之前保存的数据。在iOS开发中,有很多数据持久化的方案,接下来我将尝试着介绍一下5种方案:
plist文件(属性列表)
preference(偏好设置)
NSKeyedArchiver(归档)
SQLite 3
CoreData
沙盒
在介绍各种存储方法之前,有必要说明以下沙盒机制。iOS程序默认情况下只能访问程序自己的目录,这个目录被称为“沙盒”.
//沙盒主路径
//程序运行期间,系统会生成一个专属的沙盒路径,应用程序在使用期间的非代码文件都存储在当前的沙盒路径里面
NSArray *documentPathArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSLog(@"%@",documentPathArray);
//第一个参数:要查询文件的路径
//第二个参数:要查询路径所属的用户(iOS为单用户)
//第三个参数:YES是绝对路径,NO是相对路径
#pragma mark library 用于保存程序运行期间生成的语言
NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)firstObject];
NSLog(@"libraryPath = %@",libraryPath);
#pragma mark caches文件 用于保存程序运行期间产生缓存文件
NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)firstObject];
NSLog(@"cachesPath%@",cachesPath);
#pragma mark Preferences 文件夹 用来保存程序偏好设置
//
// NSString *preferencePath = [NSSearchPathForDirectoriesInDomains(NSPreferencePanesDirectory, NSUserDomainMask, YES)firstObject];
//
// NSLog(@"preferences%@",preferencePath);
写入文件(plist文件)
#pragma mark --NSString 写入文件
//1.准备字符串
// NSString *string = @"I love my iOS teacher's phone";
//
// //2.准备路径
//
// NSString *path = NSHomeDirectory();
// path = [path stringByAppendingString:@"/咒语.txt"];
//3.写入文件
// [string writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];
//第一个参数:路径
//第二个参数:是否进行线性操作(yes的时候,保证发生意外时,有中转文件保存信息,直至写入完成,但是损耗大,no的时候,写入速度快,但是没有安全保障)
//第三个参数:编码方式
//第四个参数:错误对象
//4.打印path
// NSLog(@"%@",path);
// //5读取文件
// //第一个参数:路径
// //第二个参数:编码方式:(切记要和写入时用的相同的编码方式)
// //第三个参数:错误信息
//
// NSString *contentString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
// NSLog(@"%@",contentString);
同样的简单对象(NSString,NSArray,NSDictionary;NSData)我们都可以用这种方法写入文件来实现数据持久化.
#pragma mark NSData 写入文件
// //1获取图片对象
// UIImage *image = [UIImage imageNamed:@"image1.png"];
//
// //2.准备路径
// NSString *homePath = NSHomeDirectory();
// homePath = [homePath stringByAppendingPathComponent:@"image1.png"];
// //将图片对象转化成data
//
// NSData *data = UIImagePNGRepresentation(image);
//
// [data writeToFile:homePath atomically:YES];
// //读取图片
// UIImageView *imgView = [[UIImageView alloc]initWithFrame:[UIScreen mainScreen].bounds];
// imgView.image = [UIImage imageWithContentsOfFile:homePath];
//
// [self.view addSubview:imgView];
复杂对象写入文档(归档)
#pragma mark ---- 复杂对象写入文件
SingleVip *vip = [SingleVip new];
vip.name = @"法特";
vip.assets = @"数不清";
vip.car = @"兰博基尼";
vip.age = 18;
NSString *homePath = NSHomeDirectory();
homePath = [homePath stringByAppendingPathComponent:@"钻石王老五.txt"];
//创建数据对象,用来存放vip对象
NSMutableData *data = [NSMutableData data];
//创建归档对象
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
//开始归档
[archiver encodeObject:vip forKey:@"vip"];
//完成归档
[archiver finishEncoding];
//写入文件
[data writeToFile:homePath atomically:YES];
NSLog(@"%@",homePath);
//反归档
//将文件里面的data对象读取出来
NSData *_data = [NSData dataWithContentsOfFile:homePath];
//创建反归档对象
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:_data];
SingleVip *_vip = [unarchiver decodeObjectForKey:@"vip"];
//完成反归档
[unarchiver finishDecoding];
NSLog(@"%@",_vip.name);
SingleVip.h
#import <Foundation/Foundation.h>
@interface SingleVip : NSObject<NSCoding>
@property(nonatomic,strong)NSString *name;
@property(nonatomic,strong)NSString *assets;//资产
@property(nonatomic,strong)NSString *car;
@property(nonatomic,assign)int age;
SingleVip.m
#import "SingleVip.h"
#define KName @"name"
#define KAssets @"assets"
#define KAge @"age"
#define KCar @"car"
@implementation SingleVip
- (void)encodeWithCoder:(NSCoder *)aCoder{
//编码
[aCoder encodeObject:_name forKey:KName];
[aCoder encodeObject:_assets forKey:KAssets];
[aCoder encodeObject:_car forKey:KCar];
[aCoder encodeInt:_age forKey:KAge];
}
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder{
if (self = [super init]) {
//反编码
_name = [aDecoder decodeObjectForKey:KName];
_assets = [aDecoder decodeObjectForKey:KAssets];
_car = [aDecoder decodeObjectForKey:KCar];
_age = [aDecoder decodeIntForKey:KAge];
}
return self;
}
归档并不是数据持久化,而是辅助复杂对象转化成简单对象的一种方式,真正实现数据持久化的仍然是writeToFile写入文件
SQLite
关于SQLite的开发资料较多,这里不再细说。只是建议不直接操作SQLite库,而是采用一些开源的第三方库来进行操作。比如:FMDB:https://github.com/ccgus/fmdb.git对SQLite都做了不错的封装。
网友评论