通信模式(Communication Patterns)
引言
看到标题的也许有一些老司机看过原文,此文是基于原文翻译加上自己理解,为了更好的学习iOS~(文章并没有写如何运用,主要是探讨什么时候用。)
原文地址:https://www.objc.io/issues/7-foundation/communication-patterns/
我们在开发过程中,常用的两个对象之间的相互通信的方式有很五种
- Target-Action
- Delegation
- block
- KVO
- Notifications
本文是讨论各个通信的使用,以及在什么时候用这些通信方式。在通信的过程中,往往一个是接收者,一个是发送者。
Target-Action
这个方式相信大家见的就很多了,在写Button或者手势的时候,都会用到addTagert
这个方法。Target-Action是用于在用户界面事件响应中发送消息的典型模式,一般是用于处理动作消息。他包含了 两个数据,一个是选择子(selector),还有一个是接收人(target)。在iOS中,能触发Target-Action事件的一般是基于UIControl的(官方文档说是可以任何对象,不过基本上都是继承与UIControl的)。一般的Target-Action的接收事件如下:
- (void)dosomething:(id)sender;
在Target-Action中,消息的接收者其实并不知道发送者是谁,发送者也不知道消息的接送者是谁。所以当target
是nil的时候,会通过响应者链找到某一个接收者去响应这个消息。这个方式的缺点就是传递消息的时候不能带着自定义的参数。
Delegation
Delegation在苹果自己的FrameWorks
里就经常使用,比如我们经常用的 tableViewdelegate
和dataSource
。它允许我们去自定义某一个对象的行为,也可以(被)告诉我们这个对象发生了什么。在这个通信过程中,消息的发送者需要知道消息的接收者,也就是这个delegate
。我们在用UITableView
的时候往往会写tableView.delegate = self
,就是让tableView
这个消息的发送者知道消息的接收者是谁(self
)。这样的耦合度会很低,大家应该都深有体会吧,哈哈哈,有时候可能会找不到这个方法在哪儿。。。
delegate protocol
可以定义任何方法,所以你也可以用这些方法传递你想要传递的参数,而且delegate protocol
可以响应这些方法返回的参数。可见delegate protocol
的通信方式是非常的灵活和直接。
block
block
也叫闭包函数,讲道理的说,只要是Delegation
通讯模式下可以做的事情,都可以用block
代替。相对来说,block
对于代码的整体性体验较好,不会散落在各地。但是blokc
会造成循环引用,也可能会提前释放。总之block
应用起来,总是对新手那么的不友好。
block
的能够抓取当前上下文的命名域,怎么说呢,就是你不需要知道这个具体是什么东西,里面是怎么样的,你可以直接更具他给的参数或者直接写你想要写的代码。
KVO
KVO
是一种通知对象的属性发生改变的机制。KVO
是一种灵活的方式去监听当前对象属性的改变,尤其是对于系统属性的监听,比如说UITableView
的ContentOffSet
这个值改变的监听,可以帮我们实现一些比较酷炫的UI效果(你懂的)。
KVO
的使用,需要一些必要的条件,比如说你的对象要支持Key-Value Observing机制。而且你要知道这个对象的生命周期,在你不需要的时候移除这个KVO
观察。
Notifications
Notifications
这通讯方式,就是一种很好的,系统给我们封装好的,一对多的广播。他最大的优势就是可以跨越层级,对代码架构的解耦很有帮助。(现在好像不能说一对多是他的优势了,貌似Swift里有多Delegate)
iOS
系统在应用过程中会发很多通知,比如说UIKeyboardWillShowNotification
,UITextViewTextDidChangeNotification
等等各种。
Notifications
和KVO
一样,需要知道接收者的生命周期,在最后生命周期结束的时候注销这个Notifications
。iOS
大部分的生命周期结束的时候都会调用- (void)dealloc
。所以其实用起来也比较简单。(当然你要是发生循环引用导致当前对象不能释放,那就没办法了(⊙﹏⊙)b)。
讨论
对比了这五种方式,那我们什么时候用呢。上面文章的作者给了这么一张图:
通讯模式.png我想分享下自己对于通讯模式的看法。因为不会画图,画在纸上的话,字太丑了,就写文字吧。。。。
1.是否直接进行对象的交互而且不需要参数,比如说手势,Button这些的 。如果是的话,就用Target-Action
。
2.是否是多层级的,两个对象是否有联系,如果不是的话,就可以用Notifications
。
3.既然两个对象是有联系的,当你需要监听值发生变化的时候,可以使用KVO
。(单存值变化,而不是其他动作响应的情况下)
4.我是否需要知道这个对象的具体东西,上下文的具体命名域。如果不需要的话,这个时候使用Block
会好一点。比如说我们网络请求时候的回调各种,只要输入请求参数,然后写好回调。中间发生了什么,其实你知道不知道,并不影响使用。
5.对于Delegation
和block
我觉得是大部分情况下是可以互相替换的,因为关于循环引用这方面,现在各种WeakSelf
,StrongSelf
的文章。不过在某些情况,比如说你的消息发送者需要用到接收者给的返回值的时候,这个时候用Delegation
在设计上来说比Block
更好。
End
其实对于通讯模式这种理解,对于整体架构,包括响应式编程都有很好的帮助。