用于管理观察者的 Objective-C 设计模式
Posted
技术标签:
【中文标题】用于管理观察者的 Objective-C 设计模式【英文标题】:Objective-C design pattern for managing observers 【发布时间】:2012-12-23 22:59:20 【问题描述】:在我的应用程序中,我有一个对象,它封装了通过 HTTP 与服务器的通信。 如果服务器上发生更改,例如会话不再有效,或者有新消息给用户等,此对象会发出一些 HTTP 请求以“轮询”。
应用程序的 UI 对象必须将自己注册到通信对象才能通过 UI 对象实现的协议接收通知。注册是通过如下方法完成的:
[communicationObject addObserver: self];
并删除自身:
[communicationObject removeObserver: self];
通信对象将观察者存储在一个可变数组中。在某些情况下,UI 对象是在 UINavigationController 中推送的 UIViewController。在那种情况下,当用户回到父控制器时,UI控制器并没有被释放,因为通信对象的观察者数组保留了它,并且UI控制器不能将自己从观察者中移除,因为dealloc 方法永远不会被调用(显然)。
问题:这个观察者通知器是一个糟糕的设计模式?有没有不使用viewWillDisappear方法检测到UI控制器被父控制器释放的方法?有解决此类情况的最佳做法吗?
【问题讨论】:
我忘记指定内存管理是由 ARC 完成的 基本上听起来不错。虽然我从未尝试过,但您应该能够创建一个包装器对象,其中包含对您的观察者对象的weak
引用,并将其放在您的列表中。然后您可以检测观察者是否已被释放。但是,如果一个对象在您对其进行操作时同时被释放,这可能会有点棘手,因此您需要仔细考虑一下。
【参考方案1】:
最佳实践
如果您使用观察者模式,并且您希望视图控制器在屏幕上观察一个值仅,最好在viewDidAppear
中调用addObserver:
,和removeObserver:
中的viewWillDisappear
。这不是错误的设计或滥用这些方法;实际上,这是标准做法,也是对这些视图控制器方法的很好使用。
如果您希望视图控制器继续观察一个值即使在它从屏幕上移除后,首先确保这确实是您想要的。如果是的话,有几件事要记住:
特别是,确保您的视图控制器设置为,如果它以前存在并且新出现在屏幕上,它会具有相同的状态,就好像它是从头开始实例化并立即出现在屏幕上一样。一种体面的方法(通常是我在自己的项目中所做的)是将所有设置代码保存在setup
方法中,并确保在实例化和演示时都调用它。
此外,请务必避免在后台引发昂贵的无关计算。通常,这可以通过在呈现视图控制器时调用 setup
方法来完成,而不是在对象的生命周期内保持一致的状态。
最后,一定要记住,视图控制器只有在屏幕上时才连接其出口(视图/子视图,通常统称为视图层次结构)。当它关闭但保留时,这些都是nil
。检查其视图层次结构是否就绪的一个好方法是通过isViewLoaded
属性。
保留与展示
这里重要的是不要混淆视图控制器(或任何对象,就此而言)被保留某处,并且它是在屏幕上的想法。这些是非常不同的事件,而且通常不会重合。例如,如果您有一个“父”视图控制器(例如UINavigationController
)管理一个或多个“子”视图控制器,则可能会同时实例化和保留多个视图控制器,而只呈现一个一次出现在屏幕上。
更好:NSNotificationCenter
如果您愿意,处理全局事件的另一个选项是通过NSNotificationCenter
,它允许您指定selector
来调用观察者,允许匿名发布通知,并允许关联任意事件对象 (userInfo
)带有通知事件。这样,您的communicationObject
将向[NSNotificationCenter defaultCenter]
发布通知,而您的视图控制器将观察defaultCenter
上的通知。您仍然可以以类似的方式添加/删除观察者对象,但您会获得一种集中的、更强大的方式来协调全局事件。
【讨论】:
嗨瑞恩,首先,感谢您的回答。我不会使用 viewDidAppear 和 viewWillDisappear,因为当 UI 视图实际上消失时,它仍然应该对通知做出反应,否则当用户返回视图时,这已经过时了......一些建议? @MarcoJacovone:我已经编辑了我的答案,包括如何处理像你这样的案例的详细信息。 非常感谢大家。最后采用了 Ryan 的第一个(of points)策略:UI 对象一直在接收通知,直到出现在屏幕上。当它消失时,注销自己。当它再次“viewWillAppear”时,它设置它的状态并再次注册到通信对象。清晰的工作理念。谢谢瑞恩。 我会考虑使用 NSNotificationCenter 进行未来的审查。 @MarcoJacovone 很高兴为您提供帮助!以上是关于用于管理观察者的 Objective-C 设计模式的主要内容,如果未能解决你的问题,请参考以下文章