Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective-C design pattern for managing observers

In my application I have an object that encapsulates communication to the server through HTTP. This object make some HTTP requests to "poll" if there are changes on the server, such as session is no longer valid, or there are new messages for the user, and so on.

UI objects of the application must register itself to the communication object to receive notifications through a protocol that UI object implements. Registration is done with a method like:

[communicationObject addObserver: self];

and to remove itself:

[communicationObject removeObserver: self];

The communication object store observers in a mutable array. In some cases, UI objects are UIViewControllers that was pushed in a UINavigationController. In that case, when the user back to the parent controller, the UI controller is not disposed, because the observer array of the communication object retain it, and the UI controller can't remove itself from the observer because the dealloc method is never called (obviously).

The question: this observer-notifier is a bad design pattern? There is a way to detect that the UI controller was released by the parent controller without using the viewWillDisappear method? There are best practice to address this type of situations?

like image 431
Marco Jacovone Avatar asked Jan 09 '13 17:01

Marco Jacovone


1 Answers

Best Practices

If you are using the observer pattern, and you want a view controller to observe a value only while it on the screen, it is a good idea to call addObserver: in viewDidAppear, and removeObserver: in viewWillDisappear. This is not bad design or misuse of these methods; actually, this is standard practice and a very good use of these view controller methods.

If you want a view controller to continue observing a value even after it gets removed from the screen, first be sure this is really what you want. If it is, there are a few things to remember:

  • In particular, make sure your view controller is set up such that it would have the same state if it previously existed and were newly brought to the screen as if it were instantiated from scratch and immediately brought to the screen. One decent way to do this (and usually what I do in my own projects) is to keep all setup code in a setup method, and make sure it is called both on instantiation and presentation alike.
  • Also, be sure to avoid incurring expensive extraneous computations in the background. Often, this can be accomplished by relying on a setup method being called when a view controller is presented, rather than maintaining a consistent state for the life of the object.
  • Finally, be sure to remember that a view controller only has its outlets (views/subviews, often collectively called the view hierarchy) connected when it is on screen. When it is off, but retained, these are all nil. A good way to check whether its view hierarchy is ready is via the isViewLoaded property.

Retention v. Presentation

It is important here not to confuse the ideas of a view controller (or any object, for that matter) being retained somewhere, and it being on screen. These are very different events, and often do not coincide. For example, if you have a 'parent' view controller (such as an UINavigationController) managing one or more 'child' view controllers, there may be multiple view controllers instantiated and retained at one time, while only a single one is presented on screen at a time.

Even better: NSNotificationCenter

If you prefer, another option for handling global events is via NSNotificationCenter, which lets you specify a selector to call on observers, lets notifications be posted anonymously, and lets arbitrary event objects (userInfo) be associated with notification events. In this way, your communicationObject would post notifications to [NSNotificationCenter defaultCenter], and your view controllers would observe notifications on the defaultCenter. You would still add/remove observer objects in a similar way, but you get a centralized, more robust way of coordinating global events.

like image 53
Ryan Artecona Avatar answered Sep 28 '22 18:09

Ryan Artecona