热门标签 | HotTags
当前位置:  开发笔记 > IOS > 正文

详解Objective-C设计模式编程中对备忘录模式的运用

这篇文章主要介绍了Objective-C设计模式编程中对备忘录模式的运用,文中结合了Cocoa框架下应用的实例来加以讲解,需要的朋友可以参考下

基本理解
这个模式有三个关键角色:原发器(Originator)、备忘录(Memento)、看管人(caretaker)。三者的基本关系是:原发器创建一个包含其状态的备忘录,并传给看管人。看管人不知道如何与备忘录交互,但会把备忘录放在一个安全之处保管好。
备忘录(Memento):在 不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象回复到原先保存的状态。
Originator(发起人):负责创建一个备忘录,用以记录当前时刻它的内部状态,并且可使用恢复备忘录内部状态。Originator可根据需要决定Memento存储Originator的哪些内部状态。
Memento(备忘录):负责存储Originator对象的内部状态,并可防止Originator以外的其他对象访问备忘录。备忘录有两个接口,CareTaker
只能看到备忘录的窄接口,它只能将备忘录传给其他对象。originator能够看到一个宽接口,允许它访问返回到先前状态所需的所有数据。
Caretaker(管理者):负责保存好备忘录,不能对备忘录的内容进行操作或检查。
就是把要保存的细节给封装在了Memento中,哪一天要更改保存的细节也不用影响客户端了。

备忘录使用场合
备忘录模式比较适用于功能比较复杂的,但需要维护或记录属性历史的类,或者需要保存的属性只是众多属性中的一小部分时,Orignator可以根据保存的Memento信息还原到前一状态。
如果在某个系统中使用命令模式时,需要实现命令的撤销功能,那么命令模式可以使用备忘录模式来存储撤销操作的状态。有的时候一些对象的内部信息必须要保存在对象以外的地方,但是必须要由对象自己读取,这时,使用备忘录可以把复杂的对象内部信息对其他的对象屏蔽起来。
用于获取状态的接口会暴露实现接口,需要将其屏蔽起来。
它一般应用于游戏、文字处理程序的设计中,这种程序需要保存当前上下文的复杂状态的快照并在以后恢复处理。

作用
当角色的状态改变时,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。
Cocoa Touch框架中的备忘录模式
Cocoa Touch框架在归档、属性列表序列化和核心数据采用了备忘录模式。
Cocoa的归档是对对象以及其属性还有同其他对象间的关系进行编码,形成一个文档,该文档既可保存与文件系统中,也可在进程或网络间传送。对象与其他对象的关系被看做对象图的网络。
归档过程把对象保存为一种与架构无关的字节流,保持对象的标识以及对象之间的关系。对象的类型也同数据一起保存。从字节流解码出来的对象通常用于对象编码时相同的类进行实例化。使用NSCoder的具体类NSKeyedArchiver和NSKeyedUnarchiver,使用基于键的归档技术,被编码与解码的对象必须遵守NSCoding协议并实现以下方法:

代码如下:

-(id)initWithCoder:(NSCoder *)coder;
-(void)encodeWithCoder:(NSCoder *)coder;

实例
添加下面两个方法到 ViewController.m 文件:

代码如下:

- (void)saveCurrentState
{
    // 当用户退出应用之后再重新打开,他想要跟他之前退出时一样的状态
    // 退出应用,这个时候我们需要做的是把当前显示的专辑存储下来
    // 因为只有一小片信息,我们可用 NSUserDefaults 来存储信息
    [[NSUserDefaults standardUserDefaults] setInteger:currentAlbumIndex forKey:@“currentAlbumIndex”];
}

- (void)loadPreviousState
{
    currentAlbumIndex = [[NSUserDefaults standardUserDefaults] integerForKey@“currentAlbumIndex”];
    [self showDataForAlbumAtIndex:currentAlbumIndex];
}


saveCurrentState 存储当前专辑的索引到 NSUserDefaults ─ NSUserDefaults 是一个标准数据存储,iOS 用来专门存放程序设置和数据。

loadPreviousState 加载这之前存储的专辑索引。这不是备忘录模式的全部,不过你已经达到目的了。

现在,在 ViewController.m 里,滚动视图初始化之前,在 viewDidLoad 里添加下面一行:

代码如下:

[self loadPreviousState];

当程序启动的时候加载上一次存储的状态。但是你在哪里存储程序的当前状态呢?你需要使用通知来做这样的事情。当程序进入后台时,iOS 会发送一个 UIApplicationDidEnterBackgroundNotification 通知。你可利用这个通知调用 saveCurrentState。就这么方便?

在 viewDidLoad: 最后面添加下面一行

代码如下:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveCurrentState) name:UIApplicationDidEnterBackgroundNotification object:nil];

现在,当你的 app 进入后台运行后,ViewController 会自动调用 saveCurrentState 存储当前的状态。

现在,添加下面代码:

代码如下:

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

这里是确保当 ViewController 被释放时,移除类的 Observer。

构建和运行你的 app,点击到一个专辑,用 Command+Shift+H(如果你使用的是模拟器的话) 将程序在后台运行,然后关掉 app。重启 app,检查之前选择的专辑是不是居中显示:

2016323170032314.png (214×320)

专辑数据看起来是对的,但是正确的专辑封面确没有居中,哪出问题了?

这就是可选方法 initialViewIndexForHorizontalScroller 的用处!因为这个方法没有被委托执行,ViewController 在这种情况下总是会显示默认的第一个专辑封面。

修复这个问题,在 ViewController.m 中添加如下代码:

代码如下:

- (NSInteger)initialViewIndexForHorizontalScroller:(HorizontalScroller *)scroller
{
    return currentAlbumIndex;
}

现在 HorizontalScroller 的第一个视图总是会被设置成 currentAlbumIndex 索引的图片。这种方法能够确保你的 app 有一个非常棒的用户体验,并且它是可恢复的。

重新运行你的 app,滚动专辑封面,关闭 app,然后重启确保问题已经得到解决:

2016323170107827.png (214×320)

如果你查看 PersistencyManger 的初始化方法,你会注意到专辑的数据是一种硬编码,PersistencyManger 每次创建,数据也会重复创建一次。有没有一种更好的方法当专辑列表被创建的时候就存储它们呢。那么如何把专辑数据存储到文件里呢?

一种选择就是循环访问 Album 的属性,然后把它存储在一个 plist 文件里,当需要它们的时候重新创建一个 Album 的实例。这不是最好的选择,这需要你在每一个类里根据不同的数据或属性写特定的代码。例子,如果稍后你需要一个电影的类,里面有一些不同的属性,存储和加载这些数据你就需要写一些新的代码。

此外,你不能在每一个类的实例里存储私有变量,因为他们是不可访问的外部类。这就是为什么苹果要创建归档 (Archiving) 机制。


推荐阅读
  • win10电脑蓝屏代码0x000000a5无法进入系统解决方法详解
    许多用户在使用电脑的时候遇到蓝屏问题,重启无法进入系统。本文提供了解决方法:调整BIOS设置、禁用安全启动、重装系统等。如果以上方法都无法解决问题,需要重新安装一个系统。详细步骤请参考正文内容。 ... [详细]
  • 本文介绍了在Ubuntu下制作deb安装包及离线安装包的方法,通过备份/var/cache/apt/archives文件夹中的安装包,并建立包列表及依赖信息文件,添加本地源,更新源列表,可以在没有网络的情况下更新系统。同时提供了命令示例和资源下载链接。 ... [详细]
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
  • GSIOpenSSH PAM_USER 安全绕过漏洞
    漏洞名称:GSI-OpenSSHPAM_USER安全绕过漏洞CNNVD编号:CNNVD-201304-097发布时间:2013-04-09 ... [详细]
  • Jquery 跨域问题
    为什么80%的码农都做不了架构师?JQuery1.2后getJSON方法支持跨域读取json数据,原理是利用一个叫做jsonp的概念。当然 ... [详细]
  • 本文介绍了一种求解最小权匹配问题的方法,使用了拆点和KM算法。通过将机器拆成多个点,表示加工的顺序,然后使用KM算法求解最小权匹配,得到最优解。文章给出了具体的代码实现,并提供了一篇题解作为参考。 ... [详细]
  • 最近在使用cocoapods的时候,当输入podinit的时候,iOS项目目录中没有出现对应的Podfile文件.问题描述:使用podinit出现badinterpreter:No ... [详细]
  • 参考资料:cocoachina的zys475481075的文章几个单词Regular[regjʊlə]adj.定期的;有规律的Expression[ɪkspreʃ(ə)n;ek-]n. ... [详细]
  • 运行就报对我有效的解决方法是:把真机和模拟器需要的文件手动加入其中,具体请参考网络上提供的其他解决方 ... [详细]
  • jsappsugar,基于,js,语法,定义 ... [详细]
  • 2015年iOS测试现状
    本文由伯乐在线-nathanw翻译,dopcn校稿。未经许可,禁止转载!英文出处:www.mokacoding.com。欢迎加入翻译小组。几周前,我决定将将我在mokacoding ... [详细]
  • 我的iOS开发入门自学路径
    我有一个清单,列着希望在大学里完成的事。比如,学一门乐器,和朋友去旅游,搭建自己的博客,去滑翔,看各主题的书籍。其中一项是,写自己的App并且上架。去年开始,我准备完成这一项,所以 ... [详细]
  • iOS Open Source : Popover API for iPhone
    iOS Open Source : Popover API for iPhone ... [详细]
  • CocoaChina2013开发者大会演讲稿主会场陈昊芝
    2019独角兽企业重金招聘Python工程师标准CocoaChina2013开发者大会演讲稿-主会场-陈昊芝2010中国团队海外iOS收入突破50万美金,2011年中国团队国 ... [详细]
  • 最近在研究可用的第三方的图标控件,然后网上搜了之后,感觉功能比较强大的就是CorePlot了,于是就开始研究如何部署到程序中。网上关于这方面的教程比较少,大部分都是objectiv ... [详细]
author-avatar
左右印象摄影
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有