Ios 管理观察者的Objective-C设计模式

Ios 管理观察者的Objective-C设计模式,ios,objective-c,design-patterns,Ios,Objective C,Design Patterns,在我的应用程序中,我有一个通过HTTP封装与服务器通信的对象。 如果服务器上有更改,例如会话不再有效,或者用户有新消息等,此对象会发出一些HTTP请求以“轮询” 应用程序的UI对象必须将自身注册到通信对象,才能通过UI对象实现的协议接收通知。使用以下方法进行注册: [communicationObject addObserver: self]; 并将其自身移除: [communicationObject removeObserver: self]; 通信对象将观察者存储在可变数组中。在某些情

在我的应用程序中,我有一个通过HTTP封装与服务器通信的对象。 如果服务器上有更改,例如会话不再有效,或者用户有新消息等,此对象会发出一些HTTP请求以“轮询”

应用程序的UI对象必须将自身注册到通信对象,才能通过UI对象实现的协议接收通知。使用以下方法进行注册:

[communicationObject addObserver: self];
并将其自身移除:

[communicationObject removeObserver: self];
通信对象将观察者存储在可变数组中。在某些情况下,UI对象是在UINavigationController中推送的UIViewController。在这种情况下,当用户返回到父控制器时,UI控制器不会被释放,因为通信对象的观察者数组保留了它,并且UI控制器无法从观察者中移除自己,因为从未调用dealoc方法(显然)

问题:这个观察者通知程序是一个糟糕的设计模式?有没有一种方法可以检测到UI控制器是由父控制器释放的,而不使用viewwilldiscover方法?有解决这种情况的最佳实践吗?

最佳实践 如果您使用的是观察者模式,并且希望视图控制器仅在其显示在屏幕上时观察值,则最好在
视图中调用
添加观察者:
,并在
视图中调用
移除观察者:
。这不是糟糕的设计或对这些方法的滥用;实际上,这是标准实践,也是这些视图控制器方法的一个很好的用途

如果希望视图控制器在从屏幕上删除某个值后仍能继续观察该值,请首先确保这是您真正想要的。如果是,有几件事需要记住:

  • 特别是,确保视图控制器的设置使其与以前存在的视图控制器具有相同的状态,并且新显示在屏幕上,就像从头开始实例化并立即显示在屏幕上一样。实现这一点的一个好方法(通常是我在自己的项目中所做的)是将所有设置代码保存在
    setup
    方法中,并确保在实例化和表示时都调用它
  • 另外,一定要避免在后台进行昂贵的无关计算。通常,这可以通过在显示视图控制器时调用
    设置
    方法来实现,而不是在对象的生命周期中保持一致的状态
  • 最后,请务必记住,视图控制器只有在屏幕上时才连接其输出(视图/子视图,通常统称为视图层次结构)。当它关闭但保留时,这些都是
    nil
    。检查其视图层次结构是否就绪的一个好方法是通过
    isViewLoaded
    属性
保留。演示 在这里,重要的是不要混淆视图控制器(或任何对象)被保留在某处,并且在屏幕上被显示的想法。这些都是非常不同的事件,而且往往并不一致。例如,如果您有一个“父”视图控制器(例如
UINavigationController
)管理一个或多个“子”视图控制器,则一次可能会实例化并保留多个视图控制器,而屏幕上一次只显示一个视图控制器

更好的是:
NSNotificationCenter

如果愿意,处理全局事件的另一个选项是通过
NSNotificationCenter
,它允许您指定一个
选择器来调用观察者,允许匿名发布通知,并允许任意事件对象(
userInfo
)与通知事件关联。这样,您的
通信对象将向
[NSNotificationCenter defaultCenter]
发布通知,视图控制器将观察
defaultCenter上的通知。您仍然可以以类似的方式添加/删除观察者对象,但您可以获得一种集中的、更健壮的方式来协调全局事件。

我忘了指定内存管理是由Arc完成的,基本上听起来不错。虽然我从未尝试过,但您应该能够创建一个对您的observer对象具有
引用的包装器对象,并将其放在列表中。然后,您可以检测观察者是否已解除分配。但是,如果一个对象在您对其进行操作时同时被解除分配,则可能会有点棘手,因此您需要仔细考虑一下。嗨,Ryan,首先,感谢您的回答。我不会使用ViewDidDisplay和ViewWillEnglish,因为当UI视图实际消失时,它仍应对通知作出反应,否则当用户返回视图时,这是过时的。。。一些建议?@MarcoJacovone:我已经编辑了我的答案,包括如何处理像你这样的案件的细节。非常感谢大家。最后采用了Ryan的第一个(分数)策略:UI对象在屏幕上显示之前接收通知。当它消失时,取消注册。当它再次“查看将出现”时,它将设置其状态并再次注册到通信对象。清晰的工作原理。谢谢赖安。我会考虑使用NSnNoTrimeCtices中心来为将来的评论服务。@ MarcoJacovone Glad帮助!