Reputation: 1132
Let's say we have a first Object 'Controller' and it initializes another object named 'Tasks' while passing 'self' for reference. Tasks object can now communicate and send messages to the super 'Controller' object. Is this correct for communicating between objects? Is this how its usually done? I've just started to really learn about programming so Im wondering if this is ok. Up until this point, I've relied on delegates and notifications. Is this good practice?
Example:
// Controller Object
task = [[Task alloc] initWithController: self];
- (void) runMethod: (NSString *) incoming {
NSLog(@"%@", incoming);
}
// Task Object
- (id) initWithController: (Controller *) ctrlr {
controllerPointer = ctrlr;
[controllerPointer runMethod:@"hello"];
return self
}
// All this should print out "hello"
And are there any other ways of communicating, interacting between objects?
Upvotes: 3
Views: 4146
Reputation: 2822
What I have been doing lately has been including a protocol I built to handle communication, much like you specify. This allows me to separate the model and the controller, a 100% valid concern.
#import <Foundation/Foundation.h>
@protocol MMNotificationDelegate <NSObject>
- (void)acquireForwardClass:(id)f_class;
- (void)notifyForwardClass:(NSDictionary*)dict;
@end
I just make sure my class implements MMNotificationDelegate, and I handle communication via this route going 'up,' and via straight method calls going 'down' among classes.
Upvotes: 1
Reputation: 26859
This is not the usual way that controller objects (Controller
in your example) and model objects (Task
) typically interact. There are a wide variety of interpretations of the Model-View-Controller (MVC) pattern, but generally speaking, controller objects observe or query the model objects, rather than relying on the models to know who their controllers are and expecting them to communicate directly with them.
Your design creates an unnecessarily tight linkage between the model and controller objects. What happens in the future if, for example, you decide to add a second controller to manage a different view of tasks? Will your Task
objects have to manage communications with multiple controllers? That could end up being a lot of code to write if you have a significant number of model objects.
In Cocoa, there are two main ways for model objects to announce events of interest to the rest of the program: notifications and key-value observing (KVO). Notifications are dead simple. You create notifications with a name and the relevant model object, then post it to a shared NSNotificationCenter
. From there, the notification center is responsible for delivering the messages to any objects that subscribe to them.
KVO is a bit more difficult to explain. Essentially, behind the scenes, Cocoa has a mechanism for detecting changes to objects and sending updated values directly to classes that observe them. (KVO also serves as part of the foundation of Cocoa Bindings, which are unfortunately not present in the iPhone SDK)
What these two techniques both have in common, though, is that they provide a generic mechanism for informing any other objects that something of interest has happened in a model object. How those objects choose to respond is entirely its own decision.
This separation makes the controller objects and model objects less dependent on one another, and it means that you, as the programmer, can worry less about the specific interactions between the controller and model layers.
Upvotes: 7
Reputation: 2927
Is this good practice?
Sure. There's nothing wrong with doing that.
If you're not using GC, you need to think about whether you want to have your Task
object retain your controller object, but in the example you've given, you almost certainly don't want to, since your Controller
object will be retaining your Task
object and you don't want a retain cycle.
A minor style comment: I wouldn't use controllerPointer
as a variable name. I'd just use controller
.
And are there any other ways of communicating, interacting between objects?
Well, you've described using notifications which is appropriate if a number of objects, rather than one specific one, might be interested in the notification. Delegates are appropriate if the Task
object really doesn't care what kind of class the delegate is.
Another approach that sometimes makes sense is if Controller
is a singleton, in which case you could do this from your Task
object.
[[Controller sharedInstance] runMethod:@"hello"];
Having said that, I think it's better practice to store the controller as a variable.
Upvotes: 2