服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - IOS - 详解Objective-C设计模式编程中对备忘录模式的运用

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

2021-01-12 15:38李刚 IOS

这篇文章主要介绍了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,检查之前选择的专辑是不是居中显示:

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

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

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

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

复制代码 代码如下:

- (nsinteger)initialviewindexforhorizontalscroller:(horizontalscroller *)scroller
{
    return currentalbumindex;
}


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

 

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

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

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

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

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

延伸 · 阅读

精彩推荐
  • IOSIOS 屏幕适配方案实现缩放window的示例代码

    IOS 屏幕适配方案实现缩放window的示例代码

    这篇文章主要介绍了IOS 屏幕适配方案实现缩放window的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要...

    xiari5772021-06-01
  • IOSiOS布局渲染之UIView方法的调用时机详解

    iOS布局渲染之UIView方法的调用时机详解

    在你刚开始开发 iOS 应用时,最难避免或者是调试的就是和布局相关的问题,下面这篇文章主要给大家介绍了关于iOS布局渲染之UIView方法调用时机的相关资料...

    windtersharp7642021-05-04
  • IOSiOS通过逆向理解Block的内存模型

    iOS通过逆向理解Block的内存模型

    自从对 iOS 的逆向初窥门径后,我也经常通过它来分析一些比较大的应用,参考一下这些应用中某些功能的实现。这个探索的过程乐趣多多,不仅能满足自...

    Swiftyper12832021-03-03
  • IOSIOS开发之字典转字符串的实例详解

    IOS开发之字典转字符串的实例详解

    这篇文章主要介绍了IOS开发之字典转字符串的实例详解的相关资料,希望通过本文能帮助到大家,让大家掌握这样的方法,需要的朋友可以参考下...

    苦练内功5832021-04-01
  • IOSiOS中tableview 两级cell的展开与收回的示例代码

    iOS中tableview 两级cell的展开与收回的示例代码

    本篇文章主要介绍了iOS中tableview 两级cell的展开与收回的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    J_Kang3862021-04-22
  • IOS解析iOS开发中的FirstResponder第一响应对象

    解析iOS开发中的FirstResponder第一响应对象

    这篇文章主要介绍了解析iOS开发中的FirstResponder第一响应对象,包括View的FirstResponder的释放问题,需要的朋友可以参考下...

    一片枫叶4662020-12-25
  • IOS关于iOS自适应cell行高的那些事儿

    关于iOS自适应cell行高的那些事儿

    这篇文章主要给大家介绍了关于iOS自适应cell行高的那些事儿,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的...

    daisy6092021-05-17
  • IOSiOS 雷达效果实例详解

    iOS 雷达效果实例详解

    这篇文章主要介绍了iOS 雷达效果实例详解的相关资料,需要的朋友可以参考下...

    SimpleWorld11022021-01-28