Objective-C / Cocoa: Proper Design for Delegates and Controllers

Consider the following general situation:

You have a MainView in a Cocoa application downloaded from an NIB that is controlled by a MainViewController . Your MainView contains some controls, such as UILabel infoLabel . You also have a MyDelegate delegate class that receives some kind of event.

You want to make sure that when MyDelegate receives its event, infoLabel updated accordingly. However, the problem is that MyDelegate does not have a link to the MainView or MainViewController and does not know about the label.

One solution is to pass the MainViewController link to the delegate object, but this seems to be wrong because you might be in an undesirable situation where the object has a link to each other.

What is the right design to solve this problem?

+7
design objective-c cocoa touch
source share
4 answers

In an unnamed developer forum, someone writes:

So, to make a short story, I decided that I would start using NSNotifications. The Stanford online course, followed by people, is taught by two Apple engineers. They just now explicitly said NOT to use the application delegate or global variables and said to use NSNotifications, delegates, and KV observations.

If this is what Apple engineers say, I'm going to move in that direction.

NSNotifications are quite brilliant in that they really don't interfere with encapsulation. The listener only listens to the notification and the object - I don’t think he should know or care about who sent it.

So, in your example, I would think that the delegate sends a notification that the label has changed, or, even better, the controller monitors this property, if possible.

+4
source share

Here are two options that come to mind:

  • If the event dispatched by the delegate is dispatched by your controller, you can return this method to the controller to click on the view.

  • You can also bind the infoLabel value to some key (using, say, Cocoa bindings or just raw monitoring of key values). A related object (which may be a delegate or some other model object) can simply update the associated key, which will call the value for infoLabel. For example, you can bind the delegate "info" to the value of infoLabel. When a delegate receives an event, he can update the member information and the presentation will change. The actual binding can happen in IB (if your delegate is in nib) or in the controller (which has a link to the view and delegate.)

The last solution is basically a circular link, but one that seems somehow cleaner to me.

+2
source share

We have implemented a complex "Data" object that controls almost everything. It checks for changes and saves all global changes.

When creating new instances, I relate to the Data class as follows:

 [[Button alloc] initWithData:data]]; 

Where data is the singelton data class. Now we can check if there are any changes needed to respond.

I admit that it still requires links, as you described. There seems to be no simple parent link.

0
source share

The usual pattern is, as you said, to pass a pointer to the MainView through its delegation methods. So, if MainView calls its doSomethingWithFoo: delegate method, you want to change this method to:

 - (void)mainView:(MainView *)view doSomethingWithFoo:(id)foo 

and call the new method accordingly. If you are working directly with the MainView pointer, you should not have problems with circular links.

-one
source share

All Articles