Delegation - I'm confused


#1

If this question seems confused that’s because I am. So apologies in advance.

I understand the concept of delegation - I think. Namely to help with loose coupling between objects in the MVC pattern but in the core location example we’re working on here I would say that the locationManager object is our model so why is it an instance variable of the controller and not a separate class by itself ? This seems to be an (M+C)V pattern. So why the need for delegation? Yes I know the documentation says you have to use delegation with CLLocationManager so that’s the way the API has been designed but the rationale for it doesn’t make sense to me for this project.

Which leads me to the second part of my confusion. I realise that it is possible to define your own delegate protocol and that is a bridge yet to be crossed by me but in iOS how do you know which classes support/need delegation. Is it simply a matter of becoming more familiar with the API or am I missing something that is blindingly obvious?

See I told you I was confused.

Gav


#2

Heh, don’t worry. These are good questions to have at this point in the book. A lot of this becomes more clear later on, but here is some help for now:

Yes, your thoughts on the concept of delegation are correct. However, your thoughts on MVC are a bit off - a controller must have pointers to model objects in order to access them. Typically, this means a controller will have an instance variable that points at its model object(s). So, while locationManager is (arguably) a model object, it doesn’t lose its model object status just because a controller has a pointer to it. Keep in mind, the locationManager is NOT inside the controller, but exists as its own object elsewhere in memory. The controller simply know where that object is by keeping an instance variable that points to it. Your suggestion is that you produce another layer between the controller and the locationManager… which would mean the controller would have an instance variable that points at that object anyhow, so you’d just be writing redundant code.

In general, delegation is an object-oriented approach to callbacks. Overall, there are 4 main callback types in Cocoa: target-action (this is what buttons use), blocks (you’ll see these later), notifications (you’ll see these later, too) and delegation. Delegation is used when an object’s actions can produce multiple outcomes. If you think about a button, there’s really only one outcome: it was tapped. Thus, you register one object to receive one message when that outcome occurs. The location manager, on the other hand, can figure out the location, the heading, or fail, and thus has multiple outcomes. The delegate protocol lists all the possible outcomes. Then, you register one object to receive ALL the messages for each possible outcome.

Another example you will see later is NSURLConnection, which is used to pass and retrieve data from a server. Its delegate gets informed when new data is available, when the connection has completed or when the connection has failed. It is a very common pattern in Cocoa Touch simply because it makes the implementation of the delegate object a lot easier - you don’t have to register each message individually, you simply set up the delegate and implement the methods you want to know about.

(Check out page 499 for a deeper discussion).


#3

Thank you. I shall mull over this tonight. I’m not sure if I’m less confused or if my brain is simply full at the moment. When you say “Typically” what would be atypical?

So can I infer that in a typical iOS MVC pattern the controller is in essence the “root object”. It will have instance variables that point to its model objects (because it needs to update the model) and instance variables that will point to its view (and subview) objects because it needs to update it’s views.

I’m off to empty my brain for the night.

Gav


#4

I’ve mulled and emptied a bit and this bit actually makes sense. Thank you.

Gav


#5

I say typically because later on you will learn about store objects, which are singletons that handle fetching model objects for you (from the filesystem, caches, servers, etc.) and the controller does not keep a pointer to these store objects because they are accessible anywhere. But still, the controller ends up having a pointer to a model object if it is ever going to display the model object’s data in one of its views.

And yes, viewing the controller as the root is a good way to look at it. Of course, when you get into apps with multiple controllers, there will be a “root of all roots.”