IOS OS X 中集中消息的传递机制
1 KVO (key-value Observing)
是提供对象属性被改变是的通知机制。KVO的实现实在Foundation中,很多基于 Foundation 的框架都依赖与它。如果只对某一个对象的值的改变感兴趣的话。就可以使用KVO消息传递。满足KVO的前提条件:1接受者(接受对象改变的通知的对象)需要知道发送者(值会改变的对象);2,接受者需要知道发送者的生命周期,因为它需要在发送者被销毁前注销观察者身份。如果这两个要求都符合的话,这个消息传递机制可以一对多(多个观察者可以注册同一个对象的变化)
如果要在Core Data 上使用KVO的话,方法会有些许差别。这和Core Data的惰性加载(faulting) 机制有关,一旦一个managed object 被惰性加载处理的话,即使它的属性没有被改变,它还是会出发相应的观察者。
注:把属性值先取入缓存中,在对象需要的时候再进行一次访问,这在 Core Data 中是默认行为,这种技术称为 Faulting。这么做可以避免降低内存开销,但是如果你确定将访问结果对象的具体属性值时,可以禁用 Faults 以提高获取性能。
2 通知 (Notification)
要在代码中的两个不相关的模块中传递消息时,通知机制是非常好的工具。通知机制广播消息,当消息内容丰富而且无需指望接受者一定要关注的话这一招特别有用
通知可以用来发送任意消息,甚至可以包含一个userInfo字典。你可以继承NSNotification 写一个自己的通知类类自定义行为,通知的独特之处在于,发送者和接受者不需要相互知道对方,所以通知可以被用来在不同的相隔很远的模块之间传递消息。这就意味着这种消息的传递是单向的,我们不能回复通知/
3委托(Delegation)
Delegation 在平果的框架中广泛存在,它让我们能自定义对象的行为,并收到一些触发的事件,要使用Delegation模式的话,发送者需要知道接受者,但是反过来没有要求,应为发送者只需要知道接受者符合一定的协议,所以他们两者结合的很松。
应为delegation 协议可以定义任何的方法,我们可以照着自己的需求来传递消息。可以用方法参数来传递消息的内容,delegation 可以通过方悔之的形式来给发送者做出回应。如果只要在相对接近的两个模块间传递消息 delegation 是很灵活很直接的消息传递机制。
过度使用 delgation 也会带来风险。如果恋歌对相结合的很紧密,任何其中一个对象都不能单独运转,那么就不需要用delegate协议了 这些情况下,对象已经知道各自的类型 可以直接交流
块 (Block)
Block 是最近才加入 Objective-C 的,首次出现在 OS X 10.6 和 iOS 4 平台上。Block 通常可以完全替代 delegation 消息传递机制的角色。不过这两种机制都有它们自己的独特需求和优势。
一个不使用 block 的理由通常是 block 会存在导致 retain 环 (retain cycles) 的风险。如果发送者需要 retain block 但又不能确保引用在什么时候被赋值为 nil, 那么所有在 block 内对 self 的引用就会发生潜在的 retain 环。
假设我们要实现一个用 block 回调而不是 delegate 机制的 table view 里的选择方法,如下所示:
self.myTableView.selectionHandler = ^void(NSIndexPath *selectedIndexPath) {
// 处理选择
};
这儿的问题是,self 会 retain table view,table view 为了让 block 之后可以使用而又需要 retain 这个 block。然而 table view 不能把这个引用设为 nil,因为它不知道什么时候不需要这个 block 了。如果我们不能保证打破 retain 环并且我们需要 retain 发送者,那么 block 就不是一个的好选择。
NSOperation 是使用 block 的一个好范例。因为它在一定的地方打破了 retain 环,解决了上述的问题。
self.queue = [[NSOperationQueue alloc] init];
MyOperation *operation = [[MyOperation alloc] init];
operation.completionBlock = ^{ [self finishedOperation]; };
[self.queue addOperation:operation];
一眼看来好像上面的代码有一个 retain 环:self retain 了 queue,queue retain 了 operation, operation retain 了 completionBlock, 而 completionBlock retain 了 self。然而,把 operation 加入 queue 中会使 operation 在某个时间被执行,然后被从 queue 中移除。(如果没被执行,问题就大了。)一旦 queue 把 operation 移除,retain 环就被打破了。
另一个例子是:我们在写一个视频编码器的类,在类里面我们会调用一个 encodeWithCompletionHandler: 的方法。为了不出问题,我们需要保证编码器对象在某个时间点会释放对 block 的引用。其代码如下所示:
@interface Encoder ()
@property (nonatomic, copy) void (^completionHandler)();
@end @implementation Encoder - (void)encodeWithCompletionHandler:(void (^)())handler
{
self.completionHandler = handler;
// 进行异步处理...
} // 这个方法会在完成后被调用一次
- (void)finishedEncoding
{
self.completionHandler();
self.completionHandler = nil; // <- 不要忘了这个!
} @end
一旦任务完成,completion block 调用过了以后,我们就应该把它设为 nil。
如果一个被调用的方法需要发送一个一次性的消息作为回复,那么使用 block 是很好的选择, 因为这样做我们可以打破潜在的 retain 环。另外,如果将处理的消息和对消息的调用放在一起可以增强可读性的话,我们也很难拒绝使用 block 来进行处理。在用例之中,使用 block 来做完成的回调,错误的回调,或者类似的事情,是很常见的情况。
Target-Action
Target-Action 是回应 UI 事件时典型的消息传递方式。iOS 上的 UIControl 和 Mac 上的 NSControl/NSCell 都支持这个机制。Target-Action 在消息的发送者和接收者之间建立了一个松散的关系。消息的接收者不知道发送者,甚至消息的发送者也不知道消息的接收者会是什么。如果 target 是 nil,action 会在响应链 (responder chain) 中被传递下去,直到找到一个响应它的对象。在 iOS 中,每个控件甚至可以和多个 target-action 关联。
基于 target-action 传递机制的一个局限是,发送的消息不能携带自定义的信息。在 Mac 平台上 action 方法的第一个参数永远接收者。iOS 中,可以选择性的把发送者和触发 action 的事件作为参数。除此之外就没有别的控制 action 消息内容的方法了。
做出正确的选择
基于上述对不同消息传递机制的特点,我们画了一个流程图来帮助我们在不同情境下做出不同的选择。一句忠告:流程图的建议不代表最终答案。有些时候别的选择依然能达到应有的效果。只不过大多数情况下这张图能引导你做出正确的决定。

图中有些细节值得深究:
有个框中说到: 发送者支持 KVO。这不仅仅是说发送者会在值改变的时候发送 KVO 通知,而且说明观察者需要知道发送者的生命周期。如果发送者被存在一个 weak 属性中,那么发送者有可能会自己变成 nil,那时观察者会导致内存泄露。
一个在最后一行的框里说,消息直接响应方法调用。也就是说方法调用的接收者需要给调用者一个消息作为方法调用的直接反馈。这也就是说处理消息的代码和调用方法的代码必须在同一个地方。
最后在右下角的地方,一个选择分支这样说:发送者能确保释放对 block 的引用吗?这涉及到了我们之前讨论 block 的 API 存在潜在的 retain 环的问题。如果发送者不能保证在某个时间点会释放对 block 的引用,那么你会惹上 retain 环的麻烦。
IOS OS X 中集中消息的传递机制的更多相关文章
- iOS中消息的传递机制
本文中,会经常提及接收者[recipient]和发送者[sender].在消息传递机制中具体是什么意思,我们可以通过一个示例来解释:一个table view是发送者,而它的delegate就是接收者. ...
- iOS之UITableView中的cell因为重用机制导致新的cell的数据出现重复或者错乱
UITableView中的cell可以有很多,一般会通过重用cell来达到节省内存的目的:通过为每个cell指定一个重用标识符(reuseIdentifier),即指定了单元格的种类,当cell滚 ...
- ENode 1.0 - 消息的重试机制的设计思路
项目开源地址:https://github.com/tangxuehua/enode 上一篇文章,简单介绍了enode框架中消息队列的设计思路,本文介绍一下enode框架中关系消息的重试机制的设计思路 ...
- java參数传递机制浅析
欢迎转载,转载请声明出处! ----------------------------------------- 前言: java语言中,參数的传递仅仅有一种机制.那就是值传递. 举例: 以下将通过几个 ...
- iOS和OS X中的bundle
bundle也可以称之为包(package). 它在iOS和OS X中实际为一个文件夹但却当成单独的文件来对待. 每一个app都有一个bundle,并且你可以通过在xxx.app图标上右击鼠标然后选择 ...
- ios 中局部变量可以通过传递来进行管理和释放,借此可提高代码的內聚度
ios 中 局部变量可以通过传递来进行管理和释放,通过多使用局部变量,可以提高代码的內聚度.如下: -(void)someMethod { UILabel *label = [[UILabel al ...
- iOS开发系列--通知与消息机制
概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户感兴趣的那么通过通知机制就可以告诉用户此时发生的事情.iOS中通知机制又叫消息机制,其包括两类:一类是本地 ...
- iOS/OS X线程安全的基础知识
处理多并发和可重入性问题,是每个库发展过程中面临的比较困难的挑战之一.在Parse平台上,我们尽最大的努力保证你在使用我的SDKs时所做的操作都是线程安全的,保证不会出现性能问题. 在这篇文章中我们将 ...
- IOS和OSX事件传递机制
本文ios部分转载自: http://zhoon.github.io/ios/2015/04/12/ios-event.html iOS的事件有好几种:Touch Events(触摸事件).Motio ...
随机推荐
- 【hdu 2222】Keywords Search
[题目链接] 点击打开链接 [算法] 此题是AC自动机模板题 AC自动机是很神奇的算法,简单点来说,就是在一棵字典树上进行KMP,它的应用范围很广,非常实用 这篇博客写得很好,推荐阅读 : http: ...
- TCP连接、释放及HTTPS连接流程
一.建立连接是三次握手 为什么三次握手?前两次握手为了确认服务端能正常收到客户端的请求并愿意应答,后两次握手是为了确认客户端能正常收到服务端的请求并愿意应答.三次握手可以避免意外建立错误连接而导致浪费 ...
- backface-visibility
浏览器支持 只有 Internet Explorer 10+ 和 Firefox 支持 backface-visibility 属性. Opera 15+.Safari 和 Chrome 支持替代的 ...
- Jquery之each函数详解
最近项目被each函数坑惨了,想来还是好好整理下关于each函数的方方面面,一来方便自己查阅,二来为读者提供经验和教训,废话不多说,来看看Each函数到底是怎么坑人的. 一. 全局jQuery.eac ...
- Educational Codeforces Round 21E selling souvenirs (dp)
传送门 题意 给出n个体积为wi,价值为ci的物品,现在有一个m大的背包 问如何装使得最后背包内的物品价值最大,输出价值 分析 一般的思路是01背包,但n*v不可做 题解的思路 We can iter ...
- bzoj 3926: [Zjoi2015]诸神眷顾的幻想乡【SAM】
有一个显然的性质就是每个串一定在某个叶子为根的树中是一条直的链 然后因为SAM里是不会有相同状态的,所以以每个叶子为根dfs一遍,并且动态构造SAM(这里的节点u的last指向父亲),最后统计答案就是 ...
- (3)javascript的数据类型
本篇学习资料主要讲解javascript中的数据类型 Javascript的数据类型 Javascript的数据类型:即一个数据不必首先做声明,可以在使用或赋值时再确定其数据的类型,当然也可以先声明该 ...
- MAC下如何配置Android手机调试(将测试手机加入到Mac系统的调试列表中)
第一步: 查看usb设备信息 在 终端输入:system_profiler SPUSBDataType 可以查看连接的usb设备的信息 比如我的usb信息如下(部分内容): 查看到我的Andr ...
- Photoshop下载
Adobe Photoshop,简称“PS”,是由Adobe Systems开发和发行的图像处理软件.Photoshop主要处理以像素所构成的数字图像.使用其众多的编修与绘图工具,可以有效地进行图片编 ...
- 关于Page翻页效果, PageViewConrtoller
Page View Controllers你使用一个page view controller用page by page的方式来展示内容.一个page view controller管理一个self-c ...