数据持久化

作者: Saxon_Geoffrey | 来源:发表于2015-03-07 19:41 被阅读410次

这篇文章将会介绍数据持久化的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

相关文章

  • Docker学习(13) 卷与持久化数据

    Docker学习(13) 卷与持久化数据 卷与持久化数据——简介 数据主要分为两种:持久化和非持久化。 持久化:就...

  • iOS本地数据持久化

    iOS本地数据持久化 iOS本地数据持久化

  • Redis-2 数据持久化及持久化配置

    一、数据持久化 开启持久化功能后,重启redis,数据会自动通过持久化文件恢复!! 1、redis持久化 – 两种...

  • 面试相关

    数据持久化 什么是持久化狭义的理解: “持久化”仅仅指把域对象永久保存到数据库中;广义的理解,“持久化”包括和数据...

  • GeekBand iOS开发高级进阶学习笔记(第四周)

    简易数据存储 数据持久化分为本体持久化和云端持久化本体持久化可以存在本地文件或数据库。云端可以存在iCloud,存...

  • iOS数据持久化

    Title: iOS数据持久化 ##数据持久化概念 数据持久化就是将内存中的数据模型转换为存储模型,以及将存储模型...

  • redis与memcache区别

    1、持久化 redis是支持持久化存储,宕机重启数据不会丢失,memcache重启后数据丢失 redis持久化的方...

  • iOS本地数据持久化

    转载自:CocoaChina - iOS本地数据持久化 本文内容:iOS本地数据持久化的几种类型iOS本地数据持久...

  • Android数据持久化的设计

    title: Android数据持久化 版 本 历 史 1. 数据持久化简介 1.1 数据持久化的需求 在网络异常...

  • 浅谈iOS持久化存储——沙盒存储

    前言 持久化是将程序数据的持久状态和瞬时状态转化的机制,通俗的讲,就是瞬时数据持久化为持久数据。持久化(Persi...

网友评论

  • 三点水老木头:楼主,这篇文章的代码在哪里可以下载 ,下一篇文章中在github下载的应该是比较复杂的,求发份962369884@qq.com :smile:

本文标题:数据持久化

本文链接:https://www.haomeiwen.com/subject/yqrvxttx.html