iOS开发基础69-应用开发中的 Controller 间通信模式
在开发 iOS 应用时,我们经常需要让不同的 controllers 之间进行通信,而不希望它们之间过于耦合。为此,我们通常会使用以下三种模式来实现通信:
- 委托(delegation)
- 通知中心(Notification Center)
- 键值观察(Key Value Observing, KVO)
模式概述
这三种模式提供了对象之间传递事件而不需要紧密耦合的方法,让不同的对象可以通知彼此某些事件的发生。下面我们详细描述每种模式的特点、优缺点以及适用场景。
一、委托(Delegation)
原理
委托模式类似于“代理”模式,一个对象(delegator)定义了一个协议(protocol),该协议中包含了一系列方法。这些方法由另一个对象(delegate)实现,并在特定时间由 delegator 调用。当某些事件发生时,delegator 通过调用 delegate 实现的方法来通知其事件的发生。
优点
- 严格的语法:在编译过程中,如果代理对象没有实现协议中的方法,将会有编译警告或错误。
- 明确的控制流程:你可以清晰地跟踪程序的控制流程,因为代码是明确调用的。
- 不需要第三方对象:通信过程无需第三方对象参与。
- 支持多协议:一个类可以实现多个协议,每个协议有不同的 delegate。
- 支持返回值:delegate 可以向 delegator 提供反馈。
缺点
- 需要定义大量代码:必须定义协议,声明 delegate 属性,并实现相关方法。
- 内存管理问题:在释放代理对象时,需要将 delegate 属性设置为 nil 以避免内存泄漏和崩溃。
- 难以实现一对多:一般情况下,委托模式是用于一对一通信。
适用场景
委托模式通常用于父子关系的对象之间(如控制器和视图)或需要返回值的场景。适合需要较强控制和明确定义的交互。
二、通知中心(Notification Center)
原理
通知中心是一种发布/订阅模型的实现。一些对象可以向通知中心发布通知,多个订阅者可以订阅并响应这些通知。
优点
- 简单的实现方式:不需要编写过多代码。
- 支持一对多通信:一个通知可以同时被多个对象接收。
- 传递上下文对象:通过 userInfo 参数,通知中心可以传递自定义的信息。
缺点
- 缺乏编译期检查:编译时不会检查通知是否能够正确处理。
- 调试复杂:因为通知机制是松散耦合的,追踪和调试通知的控制流程比较复杂。
- 需要第三方对象:通知中心作为中介管理通信过程。
- 无法获得反馈:通知发布者无法获得通知接收者的反馈。
适用场景
通知中心适用于需要在整个应用中广播消息的场景,特别是需要多对象响应同一事件的情况。如全局配置变化、用户登录状态变化等。
三、键值观察(Key Value Observing, KVO)
原理
通过键值观察,某个对象可以观察另一个对象的属性变化。对象 A 可以注册自身为对象 B 某属性的观察者,当该属性变化时,KVO 机制自动通知对象 A。
优点
- 自动同步:KVO 是实现对象间同步的简便方法,例如 model 和 view 之间的同步。
- 无侵入性:不需要改变被观察对象的实现。
- 传递属性变化信息:KVO 能提供被观察属性的最新值和之前值。
- 支持嵌套观察:通过 key paths,可以观察嵌套对象的属性。
- 抽象化:不需要额外代码来允许观察值被观察。
缺点
- 字符串定义:观察的属性通过字符串定义,编译时不会检查该字符串是否有效。
- 重构风险:属性的变更会导致观察代码不可用。
- 复杂管理:观察多个属性需要复杂的管理代码。
- 需要移除观察者:在对象释放时,需要移除所有观察。
适用场景
KVO 适用于需要属性变化通知的场景,特别是 model 和 view 之间的数据绑定和同步。
效率和适用性分析
效率
- 委托 的效率最高,因为它是直接的方法调用,且支持返回值。
- 通知中心 则效率相对较低,因为它实现了一对多的广播机制。
- KVO 的效率在特定场景下(如属性变化)非常高,但它需要处理大量的回调,不适用于大量属性和频繁变化的情况。
适用性
- 委托:用于一对一的强交互场景,特别是父子关系的对象之间。
- 通知中心:用于全局消息传递和一对多通知的情况。
- KVO:用于属性变化的监控和对象间的数据同步。
结论
这三种通信模式各有优缺点和适用场景。具体选择哪种模式,需要根据实际需求和场景进行决定:
- 对于属性层的事件,尤其是 model 和 view 的同步,使用 KVO 是最清晰且高效的。
- 对于大多数控制器间的通信,尤其是需要返回值和带有强交互的场景,使用委托模式是最合适的。
- 对于需要广播消息的场景,尤其是应用中多个对象需要响应的事件,使用通知中心更加方便。
在实际开发中,开发者应灵活运用这些模式,根据具体需求和场景选择最合适的通信方式,这样才能编写出高效、可维护的代码。
将来的你会感谢今天如此努力的你!
版权声明:本文为博主原创文章,未经博主允许不得转载。