您的位置:首页 > 移动开发 > IOS开发

iOS 设计模式系列:Archiving – 归档模式

2015-07-29 10:06 453 查看
备忘录模式就是苹果中一种归档形式。它能够把对象转化成一种数据流,在不依赖于外部类的私有属性的情况下来存储和取出数据。你可以在 iOS 6 by Tutorials 这本书的第 16
章读到更多的相关信息。或者这里 Apple’s Archives and Serializations Programming Guide。


如何使用归档 Archiving

首先,你需要声明 Album,用 NSCoding 协议来归档数据。打开 Album.h 文件,修改 @ interface 行如下:
@interface Album : NSObject <NSCoding>


在 Album.m 添加下面两个方法:
- (void)encodeWithCode:(NSCode *)aCoder
{
[aCode encodeObject:self.year forKey:@“year”];
[aCode encodeObject:self.title forKey:@“album”];
[aCode encodeObject:self.artist forKey:@“artist”];
[aCode encodeObject:self.coverUrl forKey:@“cover_url”];     [aCode encodeObject:self.genre forKey:@“genre”];
}

- (id)initWithCode:(NSCode *)aDecoder
{
self = [super init];
if (self) {
_year = [aDecoder decodeObjectForKey:@“year”];
_title = [aDecoder decodeObjectForKey:@“album”];
_artist = [aDecoder decodeObjectForKey:@“artist”];
_coverUrl = [aDecoder decodeObjectForKey:@“cover_url”];
_genre = [aDecoder decodeObjectForKey:@“genre”];
}
return self;
}


当你存档这个类的实例时调用 encodeWithCoder:。相反,当你通过解档来创建一个 Album 实例时,需要调用 iniWithCode: 。就这么简单,非常强大。

现在 Album 类可以存档了,添加的代码实际上是存储和加载专辑列表的。

在 PersistencyManger.h 里添加下面方法:
- (void)saveAlbums;


当存储专辑的时候调用些方法。

现在,在 PersistencyManger.m 里添加方法实现:
- (void)saveAlbums
{
NSString *filename = [NSHomeDirectory() stringByAppendingString:@“/Document/albums.bin”];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:albums];
[data writeToFile:filename atomically:YES];
}


NSKeyedArchiver 把专辑数组存档进一个叫 album.bin 的文件里。

当你存档的一个对象包含另一个对象的时候,存档自动递归的把子对象、子对象的子对象一并存储。在这个实例里,存储的是一个专辑实例的数组。因为数组和 Album 都支持 NSCopying 的接口,数组里的东西都会被自动存档。

现在用下面代码替换 PersistencyManger.m 里的 init 方法:
- (id)init
{
self = [super init];
if (self) {
NSData *data = [NSData dataWithContentsOfFile:[NSHomeDirectory() stringByAppendString:@“/Document/albums.bin”]];
albums = [NSKeyedUnarchiver unarchiveObjectWithData:data];
if (albums == nil) {
albums = [NSMutableArray arrayWithArray:
@[[[Album alloc] initWithTitle:@"Best of Bowie" artist:@"David Bowie" coverUrl:@"http://www.coversproject.com/static/thumbs/album/album_david%20bowie_best%20of%20bowie.png" year:@"1992"],
[[Album alloc] initWithTitle:@"It's My Life" artist:@"No Doubt" coverUrl:@"http://www.coversproject.com/static/thumbs/album/album_no%20doubt_its%20my%20life%20%20bathwater.png" year:@"2003"],
[[Album alloc] initWithTitle:@"Nothing Like The Sun" artist:@"Sting" coverUrl:@"http://www.coversproject.com/static/thumbs/album/album_sting_nothing%20like%20the%20sun.png" year:@"1999"],
[[Album alloc] initWithTitle:@"Staring at the Sun" artist:@"U2" coverUrl:@"http://www.coversproject.com/static/thumbs/album/album_u2_staring%20at%20the%20sun.png" year:@"2000"],
[[Album alloc] initWithTitle:@"American Pie" artist:@"Madonna" coverUrl:@"http://www.coversproject.com/static/thumbs/album/album_madonna_american%20pie.png" year:@"2000"]]];
[self saveAlbums];
}
}
return self;
}


在新代码里,如果文件存在,NSKeyedUnarchiver 就从文件加载专辑数据。如果不存在,它就创建专辑数据,然后立即存储,为下一次启动 app 使用。

当然你也可以在 app 后台运行的时候再存储专辑数据。现在它看起来不是很有必要,但如果你在稍后添加修改专辑数据呢?你需要确保所有的数据修改都会被存储。

在 LibraryAPI.h 添加下面的方法
- (void)saveAlbums;


因为程序的所以有服务都需要通过 LibraryAPI 提供,这就是程序为什么需要 PersistenrcyManger 来存储专辑数据。

现在在 LibraryAPI.m 中添加实现方法:
- (void)saveAlbums
{
[persistencyManger saveAlbums];
}


这里是从 LibraryAPI 调用 PersistencyManger 来存储专辑。

在 ViewController.m 文件 saveCurrentState 的后面添加下面代码:

[[LibraryAPI sharedInstance] saveAlbums];

上面的代码是每当 ViewController 存储当前状态时,使用 LibraryAPI 来存储专辑数据。

构建你的 app,检查所有的都能正确编译。

不幸的是,没有一种简单的方法来验证数据是否被正确的创建。你可以在 Finder 里检查模拟器下当前 app 的 Documents 文件夹,来看看专辑数据文件是否被创建,但是为了查看其它变化你还需要添加一些数据来改变专辑数据。

但是,为了修改数据,假使为了删除专辑而需要临时添加一个删除选项,但这个选项并不会一直在你的库中存在?此外,由于误操作,错误的删除了一个专辑,但如果给这个操作添加一个撤消选项不是很好吗?

现在是时候讨论最后一个设计模式了:命令 Command。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: