【iOS开发之Objective-C】数据持久化--文件和归档

在OC中数据持久化的方式有多种,例如:写入一个文件再或是归档。写入文件的方式我们一般都可以直接读取文件中的数据。比如我把数据写进一个XX.txt文档里面。只有数据写入成功了我就可以直接读取这个文件了。但是这样对于一些用户关键的数据并不能起到保密的作用,如果需要保密还需要使用归档操作。

文件的操作

//首先声明一个字符串
NSString * str1 = @"123456789";

方式一

直接使用方法:

- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFileencoding:(NSStringEncoding)enc error:(NSError **)error;

把一个OC的字符串写入一个txt文件中:

[str1 writeToFile:@"/Users/文件路径保密/str1.txt" atomically:YES encoding:NSUTF8StringEncoding error:nil];//先把字符串转换为二进制的数据流再写入到文件中。

方式二

先调用方法

- (NSData *)dataUsingEncoding:(NSStringEncoding)encoding;把OC字符串转换为二进制数据流,

再调用方法

- (BOOL)writeToFile:(NSString *)pathatomically:(BOOL)useAuxiliaryFile;把二进制流的数据写入文件中。

NSData * data2 = [str1 dataUsingEncoding:NSUTF8StringEncoding]; //字符串转数据流
[data2 writeToFile:@"/Users/文件路径保密/data2.txt" atomically:YES];

上述两种写入文件的数据都是最后可以直接在生产的str1.txt和data2.txt文档读取的。在目标路径中找到它,就像我们点开普通的的txt文档一样打开它就可以看见了,其实它也就是一个普通的txt文档。这就是最后的效果。


归档和解归档的操作

两个概念

深拷贝和浅拷贝。

第一种解释:像retain一样,只是对象的引用计数的加1(只是指针的拷贝),这种叫浅拷贝。像copy一样产生一个新的对象,这种叫深拷贝。

第二种解释:只是拷贝这个对象,没有拷贝对象的子对象,这种叫浅拷贝。既拷贝对象,也拷贝了它的子对象,这种叫深拷贝

归档是一种深拷贝。

《【iOS开发之Objective-C】书签管理器项目》书签管理器里面有书签。我们也可以使用归档来操作,我们只需要把书签管理器归档就可以了,书签自然就被归档进去了。

具体操作

我们要做的只有四步,如果不需要解归档,第四步的解归档可以不要。

第一步:增加一个<NSCoding>

在每个类的.h文件中:@interfaceBookMark : NSObject <NSCoding>

在NSObject 后面增加一个 <NSCoding>。

第二步:重写两个方法

在每个类的.m文件中:

重写一个解归档的方法:- (id)initWithCoder:(NSCoder *)aDecoder 和一个归档方法:

- (void)encodeWithCoder:(NSCoder *)aCoder 。这个两个方法名是固定,也不需要我们自己调用;因为在归档和解归档的时候系统会自动调用,我们只需要重写一下就可以了。怎么实现这两个方法呢?

在书签BookMark中我们做这些操作。

//解归档   我们需要解归档什么诗句在里面写什么
- (id)initWithCoder:(NSCoder *)aDecoder{
       self = [super init];
       if (self) {
              _url = [aDecoder decodeObjectForKey:@"网址"];
              _title = [aDecoder decodeObjectForKey:@"标题"];
              _stars = [aDecoder decodeIntegerForKey:@"星级"];
              _vist = [aDecoder decodeIntegerForKey:@"访问量"];
              _lev = [aDecoder decodeObjectForKey:@"权限"];
       }
       return self;
}
//归档   我们需要归档什么就在里面写什么
- (void)encodeWithCoder:(NSCoder *)aCoder{
       [aCoder encodeObject:_url forKey:@"网址"];
       [aCoder encodeObject:_title forKey:@"标题"];
       [aCoder encodeInteger:_stars forKey:@"星级"];
       [aCoder encodeInteger:_vist forKey:@"访问量"];
       [aCoder encodeObject:_lev forKey:@"权限"];
}

在书签管理器BookManager中我们也做类似的操作,我就不写在.h文件中说怎么操作了,直接看.m文件中的实现了。

//解归档
- (id)initWithCoder:(NSCoder *)aDecoder{
       self = [super init];
       if (self) {
              _array = [aDecoder decodeObjectForKey:@"管理器"];
       }
       return self;
}
//归档
- (void)encodeWithCoder:(NSCoder *)aCoder{
       [aCoder encodeObject:_array forKey:@"管理器"];
}

在上述解归档和归档中有这么两个方法:

- (id)decodeObjectForKey:(NSString *)key;
- (void)encodeObject:(id)objv forKey:(NSString *)key;

是不是有点像是字典的操作呢。注意关键词forKey。在他后面的字符串我们可以随便写,但是要保证方法之间key的对应关系和方法内key的区分

第三步:归档操作

在实现归档操作之前,我们需要新增件几个书签,我们还是使用《【iOS开发之Objective-C】书签管理器项目》中介绍的的方法增加的三个书签:

//新建一个百度的书签
BookManager   * myBookManager = [[BookManager alloc] init];
[myBookManageraddBookMarkWithUrl:@"www.baidu.com" withTitle:@"百度" withStars:3 withVist:123 withLevel:@"C"];
//新建一个新浪的书签
[myBookManageraddBookMarkWithUrl:@"www.sina.com" withTitle:@"新浪" withStars:7 withVist:456 withLevel:@"C"];
//新建一个搜狐的书签
[myBookManageraddBookMarkWithUrl:@"www.souhu.com" withTitle:@"搜狐" withStars:5 withVist:756 withLevel:@"C"];

有了这三个书签作为一个例子就可以来具体实现归档了。

NSMutableData * data1 = [[NSMutableData alloc] init];
NSKeyedArchiver * arc1 = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data1];
/*归档*/
[arc1encodeObject:myBookManager forKey:@"书签管理器"];
[arc1finishEncoding]; //封口 这一步一定在写入数据之前
[data1writeToFile:@"/Users/文件路径保密/书签类设计.txt" atomically:YES];

这里使用到了两个类:NSMutableData NSKeyedArchiver一个是先声明一个可变的数据流,一个是新建一个归档的实例。有了上述操作,其实归档已经操作完了。最后会生成一个《书签类设计.txt》的文档,但是我们却打不开它。下面这个图也证实了,里面是有内容的,但是不能像上面的文件操作那样直接看到是什么内容,而且还打不开。


有了归档操作后数据可以写入一个文件实现持久化了,而且还是保密的。但是我们看不见数据啊。难道写入的数据就不能再看见了?显然还有解归档的操作,在上面已经有了解归档这个词了。

第四步:解归档操作

解归档的操作其实很简单,上面在.m文件实现的两个解档的方法- (id)initWithCoder:(NSCoder *)aDecoder 就能发挥他们的作用了。

NSData * data2 = [[NSData alloc] initWithContentsOfFile:@"/Users/文件路径保密/书签类设计.txt"];
NSKeyedUnarchiver * uarc1 = [[NSKeyedUnarchiver alloc] initForReadingWithData:data2];
/*解归档*/
BookManager * bk1 = [uarc1 decodeObjectForKey:@"书签管理器"];     
[uarc1finishDecoding];
[bk1showAllBookMark];

①. 声明一个数据流data2来接收刚才写入《书签类设计.txt》里面的数据;

②. 解归档,使用了一个和归档相对应的类NSKeyedUnarchiver

③. 使用一个BookManager * bk1 的对象来接收解档“书签管理器”;

④. 完成解档;

⑤. 打印解档出来的数据。

打印结果:

2015-08-02 10:45:14.750 3.书签管理器[896:303] 网址:www.baidu.com 标题:百度 星级:3 访问量:123 权限:C
2015-08-02 10:45:14.752 3.书签管理器[896:303] 网址:www.sina.com 标题:新浪 星级:7 访问量:456 权限:C
2015-08-02 10:45:14.753 3.书签管理器[896:303] 网址:www.souhu.com 标题:搜狐 星级:5 访问量:756 权限:C

至此,归档和解归档的操作都介绍完了,其实实现起来并不困难。

回头再看概念

在上面介绍深拷贝和浅拷贝的时候有这么一句话:既拷贝对象,也拷贝了它的子对象,这种叫深拷贝。归档是一种深拷贝。

在上面的例子中,我们归档的是书签管理器这个对象,不是书签。在书签管理器里面有三个书签对象:分别是百度、新浪和搜狐。这三个书签对象是书签管理器的一个子对象(不是继承关系)。也就是说我们不仅拷贝了书签管理器,还拷贝了书签管理器里面的子对象--书签。

总结

在这篇中我们介绍了文件和归档、解归档的一些基本操作。在这些操作中我们不难发现这些操作的基本步骤都是相对固定的。我们只需要按照这个步骤调用方法就可以实现需要的功能,达到目的。这也是OC的一个特点,一定要注意流程。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值