27
2017
09

Delegate Notification KVO 整理

一个公共问题是我们根据经验开发iOS应用时,在不耦合的情况下如何进行控制器之间的通讯,在iOS开发中有三种不同的方案可以解决这个问题

Delegation:为控制器设置代理

Notification Center:设置通知

Key value observing:KVO

那我们应该明白这三种方案的优缺点,以便更好的使用在我们的项目中。

接下来的对于这三种方案的讨论完全是我开发iOS应用的个人见解。

我会讨论我觉得某一个特定的方案在某些情况下为什么比另一种方案好。我不给不了绝对的答案,只是一些个人见解而已。所以请各位大神在留言区自由讨论以便能给予我更多的经验和见解。

言归正传,先科普一些这三种方案到底都是什么。

这三种模式都是在没有耦合的情况下将一个对象的事件传递到另一个对象。他们是对象发送通知后按照某些途径的传播的方式,更准确的说,是让某些事件被响应对象接受到的方法。这是一种在对象间常见的必须执行的任务,如果控制器间无法进行通讯,这整个应用则无法融为一体。然后控制器的另一个作用就是必须实现自我控制。我们希望我们的控制器可以独立存在,控制器之间不存在耦合,这样方便抽取与复用。控制器可以创建其他控制器并且可以自由的联系,但是我们不想在创建控制器的时候绑定太多信息到父类中。如果控制器间产生了过多的耦合,这产生很多问题,使之失去了重用的能力,这样难以在后期维护与复用。

这三种设计模式提供了再控制器或者对象中相互联系的方法,而且不会产生耦合。我将会描述这么模式和在iOS中如何应用。不过需要注意他们在某些条件下可能不适用,这也是我后来需要讨论的内容。
代理模式

当你第一次启动iOS应用程序,你会注意到在系统提供的SDK中很多地方都是使用了 “delegates” 。代理在iOS并不算是一种固定的设计模式,这取决于你有什么样的变成背景,你可能不会立刻就想起来使用代理明显的优势和为什么他经常性的被使用。

关于代理最基本的想法,是控制器定义一套协议(定义一套方法)描述控制器需要做什么操作已让另一个控制器做出响应。这个协议需要相应控制器遵守,仿佛代理再说“如果你想成为我的代理,你必须是写这些方法”。这是控制器实现这些代理方法,相应控制器会响应相应的方法,代理可以是任何对象类型,所以控制器之间并不存在耦合,但是代理响应时,可以传入信息,告诉响应控制器相应的动作和参数。

优点:

严格的语法。所有的事件都需要在协议中清除的定义。
如果代理没有事件的话编译器会发出警告或报错。
协议定义的范围仅在控制器内, 只有控制器能定义代理。
可追踪性强,方便debug
同一个控制器可以同时遵守多个协议,
不需要第三方对象进行监控,使用简单。
代理可以通过方法传值,这样在不同控制器之间可以进行参数传递。

劣势:

需要写很多代码才能实现功能1,协议定义 2.代理需要在控制器中进行赋值,3在响应控制器中需要实现方法。
需要检查代理是否为空,如果调用空代理的话会导致程序崩溃。 
代理只能是一对一操作,不能实现一对多操作。

通知

iOS应用中有一个“通知中心”的概念。它允许一个对象发生通知后其他的对象响应通知。系统允许一个对象产生通知后再任何其他对象中以较低的耦合为代价就可以接受到通知并且响应事件和传递变量。这个方案的最基本概念是通过控制器使用一个件(通知名称)以允许其他的对象能够接受到该控制器中的特殊事件。然后其他的控制器,对象通过注册相同的通知事件以便能接受到接受到事件。

优点:

方便使用,无需过多的代码。
对个对象可以同时响应一个通知。
控制器可以通过上下文(字典)自定义信息(userinfo)通过通知进行传递达到传值的效果 
缺点:
无法在编译阶段检测错误,通知的正确性都是通过开发者来判断
如果你要销毁注册通知的对象时,需要在消息中心取消注册了的通知
在调试的时候通知会导致非常难以追踪。
需要第三方对象来管理控制器和观察者之间的关系。
所有观察者和控制器需要提前知道通知名称和userinfo dictionary key。如果不在公共区域定义这些名称,他们会非常容适出现无法同步的现象。
在通知发出后控制器不在就不能从观察者获得任何的反馈信息。

Observation

Key value observing (KVO)是一个对象能够观察另一个对象的值,并且可以捕获到改变。前两个方案(代理和通知)更加适合一个控制器和其他对象的通讯,然后KVO更加适合任意的一个对象监听任何其他对象的属性的改变(不一定单单指一个控制器)。这是一种我们能够保证同步的保持和另一个对象同步的方法;及时当一个对象的状态改变时,另一个对象也可以及时作出反应。他只能用于对于对象的属性作出反应,不能对方法和动作作出反应。

优点:

可以方便的在两个对象之间同步信息,例如一个model和一个view。
允许我们对非我们自己创建的对象即内部对象响应属性值的改变,而不需要改变其内部实现(SDK objects)。
可以提供给我们之前观察的对象的变化前的值和变化后的值。
可以用use key观察属性,也可以观察嵌套对象。
完成了对观察对象的抽象,不需要额外的代码来允许观察者进行观察。 
缺点:
我们观察的属性必须定义为string类型。这样编译器就不能做出检查。
重构属性可能会导致我们的观察者无法继续工作。
如果要同时监听多个值,可能会使用"if"等复杂语句。因为所以的KVO代码都是通过一个方法执行。
当对象销毁时需要移除观察者。
上一篇:A33 Vstar开发板简述及BSP下载 下一篇:AWS快速使用