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

IOS设计模式第九篇之备忘录模式

2013-12-27 17:13 288 查看
备忘录模式捕获和具体化对象的内部状态。换句话说,它可以节省你的东西后来,这种外部状态可以恢复在不违反封装;也就是说,私人数据是私有的。怎么用备忘录设计模式在Viewcontroller的实现文件里添加下面方法:- (void)saveCurrentState{// When the user leaves the app and then comes back again, he wants it to be in the exact same state// he left it. In order to do this we need to save the currently displayed album.// Since it's only one piece of information we can use NSUserDefaults. [[NSUserDefaults standardUserDefaults] setInteger:currentAlbumIndex forKey:@"currentAlbumIndex"];}- (void)loadPreviousState{ currentAlbumIndex = [[NSUserDefaults standardUserDefaults] integerForKey:@"currentAlbumIndex"]; [self showDataForAlbumAtIndex:currentAlbumIndex];}saveCurrentState 保存了这个当前专辑的索引用NSUserDefaults 他是一个苹果提供的标准的存储应用设置和数据的。loadPreviousState 加载之前保存的索引。这不是备忘录设计模式的完全实现。现在添加代码在滑动视图初始化前面:[self loadPreviousState];应用程序启动时加载以前保存的状态,但是你保存应用当前转台只是为了加载?你将要用通知做这件事。当应用进入到后台系统发送UIApplicationDidEnterBackgroundNotification。你可以用这个通知调用saveCurrentState。这不是很方面吗?在ViewDidLoad添加下面代码:[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveCurrentState) name:UIApplicationDidEnterBackgroundNotification object:nil];现在这个应用进入到后台。将要自动的调用saveCurrentState方法来保存当前状态。现在添加下面代码:- (void)dealloc{ [[NSNotificationCenter defaultCenter] removeObserver:self];}这个保证你Viewcontroller销毁的时候移除这个类注册的观察者。构建和运行您的应用程序。导航到一个专辑,将应用程序发送到后台使用命令+ Shift + H(如果你是在模拟器),然后关闭应用程序,重新启动,并检查之前,选择专辑为中心:看起来你的专辑数据是正确的。但是你的滑动视图没有在中间这是怎么了?这就是上面可选协议方法的意义initialViewIndexForHorizontalScroller:因为这个方法在代理类里面没有实现。在这个例子代理类就是Viewcontroller,因此初始视图一直被设置为第一个视图。为了修正他在Viewcontroller的实现文件里面添加下面代码:- (NSInteger)initialViewIndexForHorizontalScroller:(HorizontalScroller *)scroller{ return currentAlbumIndex;}现在这个滑动视图的第一个视图可以设置为任何专辑是由currentAlbumIndex表明的。这是一个很好的方法来确保你的应用体验来维持私有和可恢复的。如果你看看PersistencyManager的init,你将要注意到这个专辑数据是硬件编码并且PersistencyManager创建的时候都会重新创建。最好的解决方法是一旦创建专辑列表就把他们存储到一个文件。那么怎么把专辑存储到文件呢?一种方法是迭代专辑的属性,保存他们到一个plist文件并且然后创建专辑的实例一旦需要的时候。但是这不是最佳选择,由于需要你编写特定的代码依靠每个类的属性和数据。例如你接下来创建的movies类有不同的属性,保存和加载数据需要新的代码。此外,你不能保存每个类的实例的私有变量,因为他们无法访问外部类。这就是为什么苹果公司创建归档机制。归档苹果的一个专门记忆模式的实现是归档。把一个对象转化为流便于保存和恢复不用向外部类暴露私有的属性。你可以参考Apple’s Archives and Serializations Programming Guide.那么怎么用归档呢?首先你需要声明专辑通过符合NSCoding协议是可以归档的。在专辑头文件写上符合NSCoding协议:@interface Album : NSObject <NSCoding>在实现文件里面:添加两个方法:- (void)encodeWithCoder:(NSCoder *)aCoder{ [aCoder encodeObject:self.year forKey:@"year"]; [aCoder encodeObject:self.title forKey:@"album"]; [aCoder encodeObject:self.artist forKey:@"artist"]; [aCoder encodeObject:self.coverUrl forKey:@"cover_url"]; [aCoder encodeObject:self.genre forKey:@"genre"];}- (id)initWithCoder:(NSCoder *)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:当你归档你类的一个实例时候,相反地的当你解档一个实例来创建一个专辑的实例。看着简单而且强大。现在专辑类可以被归档了。添加的代码实际上保存和加载相册的列表。添加以下签名(或方法原型)PersistencyManager.h:这将是叫的方法保存相册。现在,添加PersistencyManager.m方法实现:- (void)saveAlbums{NSString *filename = [NSHomeDirectory() stringByAppendingString:@"/Documents/albums.bin"];NSData *data = [NSKeyedArchiver archivedDataWithRootObject:albums]; [data writeToFile:filename atomically:YES];}NSKeyedArchiver档案专辑数组名为albums.bin的文件。当你归档对象包含其他对象,归档器会自动的迭代归档子对象并且孩子的任何子对象。在此情况下开始对专辑类归档,这是专辑实例的一个数组,因此数组和专辑都支持NSCoding接口。任何在数组里面的东西都会被归档。现在在PersistencyManager.m init方法里添加下面代码:- (id)init{ self = [super init]; if (self) {NSData *data = [NSData dataWithContentsOfFile:[NSHomeDirectory() stringByAppendingString:@"/Documents/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 从文件里面加载新的专辑数据,如果他存在。如果他不存在,立即创建相册数据和保存它在下次加载应用程序。你还想保存这张专辑每次应用程序进入后台数据。这可能不是必要的,但如果你后来添加的选项更改相册数据那么你想要确保您已经保存了所有更改。添加以下LibraryAPI.h方法签名:- (void)saveAlbums;应用通过libraryAPI访问所有的服务,这就是应用怎么让PersitencyManager 知道他需要保存专辑的数据。现在添加这个方法实现到libraryAPI实现文件里:- (void)saveAlbums{ [persistencyManager saveAlbums];}这段代码仅仅通过在调用LibraryAPI保存相册到PersistencyMangaer。和上面的代码使用LibraryAPI触发保存专辑的数据每当Viewcontroller保存其状态。编译运行你的应用检查是不是所有东西运行正常。不幸的是,没有简单的方法来检查数据持久性是正确的。幸运的是你可以在finder里检查模拟器的document文件夹看专辑的数据文件是不是被创建,但是为了检查是不是有改变你不得不添加改变专辑数据的功能。但是代替改变数据,如果你添加一个选项来删除你的专辑当你不想要的时候。此外你应该有一个撤销的选项一旦你误删了专辑。这是我们下面介绍的一个设计模式命令设计模式。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: