数据持久化

这篇文章将会介绍数据持久化的4种方式:NSUserDefaults,NSFileManager,NSCoding+NSKeyedArchiver和CoreData

1.NSUserDefaults

Cocoa会为每个app自动创建一个文件,我们可以用它来存储一些较简单的数据,如音效等应用设置之类的少量信息。NSUserDefaults本质上是以Key-Value形式存成plist文件,放在/Library/Preferences/{Bundle Identifier}.plist目录下,这个文件是不安全的,所以不要用NSUserDefaults来存储密码之类的敏感信息

NSUserDefaults是一个单例,它支持保存的数据类型有:NSNumber,NSString, NSDate, NSArray, NSDictionary, BOOL.

1.写入数据

// 获取一个NSUserDefaults对象
NSUserDefaults * aUserDefaults = [NSUserDefaults standardUserDefaults];
// 插入一个key-value值
[aUserDefaults setObject:_label.text forKey:@"name"];
 
// 同步操作,为了把设置及时写入文件,防止由于崩溃等情况App内存信息丢失
[aUserDefaults synchronize];

2.读取数据

NSUserDefaults * aUserDefaults = [NSUserDefaults standardUserDefaults];
// 获取一个key-value值
NSString * aStr = [aUserDefaults objectForKey:@"name"];

值得注意的是:NSUserDefaults存储的对象全是不可变的,例如,如果我想要存储一个 NSMutableArray对象,我必须先创建一个不可变数组:

NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:@"123",@"234", nil];
NSArray * array = [NSArray arrayWithArray:mutableArray];
     
NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
[user setObject:array forKey:@"name"];

取出数据也一样:

NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
     
NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:[user objectForKey:@"name"]];

2. NSFileManager

上面提到NSUserDefaults可以存成Plist文件,只是Apple帮我们封装好了读写方法而已(事实上我们自己实现这个方法也很简单)。NSUserDefaults的缺陷是存储只能是Library/Preferences/<Application BundleIdentifier>.plist 这个文件,如果我们要自己写一个Plist文件呢? 使用NSFileManger可以很容易办到。

如果你存储的数据是Plist文件支持的类型,直接用NSFileManager的writToFile接口就可以写入一个plist文件了。Plist文件支持的数据格式有:NSString,NSNumber, Boolean, NSDate,NSData,NSArray和NSDictionary.其中,Boolean格式事实上以[NSNumber numberOfBool:YES/NO];这样的形式表示。

1).获取路径:

NSFileManager *fileManager = [NSFileManager defaultManager];

//Library目录路径:NSLibraryDirectory, Cache目录路径:NSCachesDirectory
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
//等同于以下操作
//NSString * documentsPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
NSString *directoryPath = [documentsPath stringByAppendingPathComponent:@"file"];

2).在上面的路径下创建目录:createDirectoryAtPath

if (![fileManager fileExistsAtPath:directoryPath]) {
    [fileManager createDirectoryAtPath:directoryPath withIntermediateDirectories:NO attributes:nil error:nil];
}]

3).在上面的目录下创建文件:createFileAtPath

[fileManager createFileAtPath:[documentsPath stringByAppendingString:@"/text.plist"] contents:data attributes:nil];

//获取创建的该文件的路径
filePath = [NSString stringWithFormat:@"%@%@",documentsPath,@"test.plist"];

4).写数据到文件:writeToFile

NSDictionary *dictionary = @{@"key":@"value"};
dictionary writeToFile:filePath atomically:YES];

5).读取文件的属性:attributesOfItemAtPath
例如,读取文件的创建日期:

NSDate *creationDate = nil;
if ([fileManager fileExistsAtPath:filePath]) {
    NSDictionary *attributes = [fileManager attributesOfItemAtPath:filePath error:nil];
    creationDate = attributes[NSFileCreationDate];
}

6).删除文件:removeItemAtPath

NSError *error = nil;
if (![fileManager removeItemAtPath:filePath error:&error]) {
    NSLog(@"[Error] %@ (%@)", error, filePath);
}

3.NSKeyedArchiver/NSKeyedUnarchiver

上面介绍的两种方法,通常仅支持常用数据类型,但是不支持自定义的数据类型,不过Cocoa提供了NSCoding和NSKeyArchiver两个工具类,可以把我们自定义的对象编码成二进制数据流,然后存进文件里面,如果要使用这种方式进行存储,首先自定义的对象要继承NSCoding的delegate。

NSCoding是一个简单的协议,有两个方法:-initWithCoder: 和 encodeWithCoder:。遵循NSCoding协议的类可以被序列化和反序列化,这样可以归档到磁盘上或分发到网络上。

@interface Book : NSObject <NSCoding>
@property NSString *author;
@property NSUInteger price;
@end

@implementation Book
#pragma mark - NSCoding
- (id)initWithCoder:(NSCoder *)decoder {
    self = [super init];
    if (!self) {
        return nil;
    }
    self.author = [decoder decodeObjectForKey:@"author"];
    self.price = [decoder decodeIntegerForKey:@"price"];
    return self;
}

- (void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:self.author forKey:@"author"];
    [encoder encodeInteger:self.price forKey:@"price"];
}

@end

如上,NSCoding 主要是样板文件。每个属性用属性名作为key,编码或解码成一个对象或者类型。这样,我们就定义了一个可以使用NSCoding进行编码的数据对象。

Mantle是一个意在减少写NSCoding样板文件的类库,可以看看)

Archiving(归档):

Book *books = [Book alloc] init];
//归档至目录
[NSKeyedArchiver archiveRootObject:books toFile:@"/path/to/archive"];
//归档至二进制数据
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:books];

Unarchiving(解档):

//从目录解档
[NSKeyedUnarchiver unarchiveObjectWithFile:@"/path/to/archive"];
//从文件解档
Book *book = [NSKeyedUnarchiver unarchiveObjectWithData:data];

除了归档到文件,还可以归档到NSUserDefaults。

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:books];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"books"];

Unarchiving:

NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:@"books"];
NSArray *books = [NSKeyedUnarchiver unarchiveObjectWithData:data];

所以其实使用NSCoding和NSKeyedArchiver事实上也是写入和读取文件,只不过对复杂对象进行了编码使得文件支持更多数据类型而已。

参考:Apple文档nshipsteriOS数据持久化

下一节我们介绍CoreData

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容

  • 1、 沙盒概念基本介绍 iOS 应用程序只能在该 app 的文件系统中读取。这个默认的 app 文件系统就是我们说...
    Laughingg阅读 2,637评论 2 10
  • 目录 沙盒及其结构 Preference(偏好设置)-Plist 属性列表-Plist NSKeyedArchiv...
    Ryan___阅读 471评论 0 0
  • 一、数据持久化概述 数据持久化就是数据的永久存储。其本质是将数据保存为文件,存到程序的沙盒中。 1、数据持久化的方...
    lilinjianshu阅读 595评论 0 1
  • 一、数据持久化概述 数据持久化就是数据的永久存储。其本质是将数据保存为文件,存到程序的沙盒中。 1、数据持久化的方...
    lilinjianshu阅读 479评论 0 1
  • 1.简介 数据持久存储是一种非易失性存储,在重启动计算机或设备后也不会丢失数据。持久化技术主要用于MVC模型中的m...
    公子无礼阅读 1,671评论 0 4