在平时开发过程中,我们遇到一些消息传递时候,基本还是就会用到下面三种通知机制,KVO,delegate ,通知中心Notification Center 。
下面就来简单的谈谈这三种通知机制区别和各自的优缺点。
一、代理
代理的特点是必须在C里面定义,说不上优缺点,所以就是特点。
优点:
1、相对来说,代理有最严格的语法定义,他将所有的监听到的事件必须在代理协议中都有非常清晰的定义。嗯,想想这个也算是特点吧。
2、代理协议中没有第三方对象要求保持或者监事通讯过程。
3、在代理方法中可以设置返回值进行数据通信,不仅仅是代理方法的参数。
4、代理可以设置必须实现的和可实现的代理方法,但是一旦设置必须实现的代理方法在设置代理之后,就必须实现“必须实现的方法”。听起来这么绕口。可能我语言没有组织好。
缺点:
1、相对来说代理因为是一个非常严谨的通知机制,有明确的方法参数和返回值,这样就导致了需要编写很多代码。比如属性,方法,
2、在一个C中,可以存在多个代理以及协议,也可以一个代理和协议在同一个控制器中被多个对象设置。但是使用的时候需要区分,这个也算是特点?是吧!
二:通知中心Notification Center
优点:
1、相对代理来说,只需要很少的代码量。
2、可以实现一对多的通知,发送一个通知,可以有多个对象来接收,不必想代理那样需要区分。
3、通知比较迅速。(因为是在主线程中的原因)
缺点:
1、在主线中进行通讯,比较耗费资源(有优点,也有缺点);
2、使用完毕之后必须注销通知。
3、较难追踪。
三:KVO
优点:
1、比较轻量级 可以提供一种简单的方法实现两个对象的同步。
2、比较灵活(权利比较大),可以改变一些类的内部属性等。(使用不好,也有一定的危险性)。
3、可以一对多。
4、能够提供观察的属性的最新值以及先前的值。
5、当释放观察者时不需要移除观察者。
缺点:
1、通讯只能通过string来传值。
2、一旦一些内部属性改动,之前牵扯到的KVO将不可用。
3、复杂的“IF”语句要求对象正在观察多个值。这是因为所有的观察代码通过一个方法来指向。
1、效率 肯定是delegate比NSNotification高。
delegate方法比notification更加直接,最典型的特征是,delegate方法往往需要关注返回值, 也就是delegate方法的结果。比如-windowShouldClose:,需要关心返回的是yes还是no。所以delegate方法往往包含 should这个很传神的词。也就是好比你做我的delegate,我会问你我想关闭窗口你愿意吗?你需要给我一个答案,我根据你的答案来决定如何做下一 步。相反的,notification最大的特色就是不关心接受者的态度, 我只管把通告放出来,你接受不接受就是你的事情,同时我也不关心结果。所以notification往往用did这个词汇,比如 NSWindowDidResizeNotification,那么NSWindow对象放出这个notification后就什么都不管了也不会等待接 受者的反应。
2、KVO和NSNotification的区别 :
两者都是观察者模式,不同的是,KVO是被观察者直接发送消息给观察者,是对象间的交互,而通知则是观察者和被观察者通过通知中心对象之间进行交互,即消息由被观察者发送到通知中心对象,再由中心对象发给观察者,两者之间并不进行直接的交互。
和delegate一样,KVO和NSNotification的作用也是类与类之间的通信,与delegate不同的是
1)这两个都是负责发出通知,剩下的事情就不管了,所以没有返回值;
2)delegate只是一对一,而这两个可以一对多。这两者也有各自的特点。
总结:
从上面的分析中可以看出3中设计模式都有各自的优点和缺点。其实任何一种事物都是这样,问题是如何在正确的时间正确的环境下选择正确的事物。下面就讲讲如何发挥他们各自的优势,在哪种情况下使用哪种模式。注意使用任何一种模式都没有对和错,只有更适合或者不适合。每一种模式都给对象提供一种方法来通知一个事件给其他对
象,而且前者不需要知道侦听者。在这三种模式中,我认为KVO有最清晰的使用案例,而且针对某个需求有清晰的实用性。而另外两种模式有比较相似的用处,并且经常用来给controller间进行通信。那么我们在什么情况使用其中之一呢?
根据我开发iOS应用的经历,我发现有些过分的使用通知模式。我个人不是很喜欢使用通知中心。我发现用通知中心很难把握应用的执行流程。Userlnfo dictionaries的keys到处传递导致失去了同步,而且在公共空间需要定义太多的常量。对于一个工作于现有的项目的开发者来说,如果过分的使用通知中心,那么很难理解应用的流程。
我觉得使用命名规则好的协议和协议方法定义对于清晰的理解controllers间的通信是很容易的。努力的定义这些协议方法将增强代码的可读性,以及更好的跟踪你的app。代理协议发生改变以及实现都可通过编译器检查出来,如果没有将会在开发的过程中至少会出现crash,而不仅仅是让一些事情异常工作。甚至在同一事件通知多控制器的场景中,只要你的应用在controller层次有着良好的结构,消息将在该层次上传递。该层次能够向后传递直至让所有需要知道事件的controllers都知道。当然会有delegation模式不适合的例外情况出现,而且notification可能更加有效。例如:应用中所有的controller需要知道一个事件。然而这些类型的场景很少出现。另外一个例子是当你建立了一个架构而且需要通知该事件给正在运行中应用。
根据经验,如果是属性层的时间,不管是在不需要编程的对象还是在紧紧绑定一个view对象的model对象,我只使用观察。对于其他的事件,我都会使用delegate模式。如果因为某种原因我不能使用delegate,首先我将估计我的app架构是否出现了严重的错误。如果没有错误,然后才使用notification。
(我是站在巨人的肩膀上,加上自己的理解,如有错误,恳请多多指教)