Since delegate is a simple variable, assigning to it overwrites the value rather than adding to it. You could convert it to an array, but because NSArray keeps strong references to the objects within it you need to deal with potential circular references. (A circular reference in this case is that two objects own each other. Since they're both owned by someone, neither will be freed. Even though they only own each other. Wikipedia has more. But the typical pattern in Objective-C is to make all delegates weak for this reason.)
Instead of delegates, you may wish to consider using NSNotificationCenter
notifications.
Instead of 1:1, they're 1:any (including 0 without special considerations). The idea is that one object posts a notification, and the objects that are interested in it observe it. Each object can pick which events they're interested in.
There's a few steps you'll need to perform:
- Remove all the delegate code you've written.
- Agree on a notification name.
- Register the objects that will respond to the notification. (This is where you set the delegate.)
- Handle the notification.
- Post the notification (where you previously called the delegate).
- Unregister the objects when they're destroyed.
What you would do is agree on a key, probably in a constant.
Keys.h:
extern NSString *MethodOneNotification;
Keys.m:
NSString *MethodOneNotification = @"MethodOneNotification";
Then register in firstViewController
and secondViewController
like this somewhere like viewDidLoad
:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(methodOneNotification:) object:nil];
Provide a handler in both firstViewController
and secondViewController
for the selector:
- (void)methodOneNotification:(NSNotification *)notification {
NSLog(@"%@ got the notification!", [self class]);
}
Call the notification where you previously called the delegate:
[[NSNotificationCenter defaultCenter] postNotificationName:MethodOneNotification
object:nil];
And in both firstViewController
and secondViewController
, you'll want to remove the notification registration (certainly in dealloc):
- (void)dealloc {
[[NSNotification defaultCenter] removeObserver:self name:MethodOneNotification
object:nil];
// [super dealloc] if you're not using ARC, but you should be
}
Within the notification handler, you can access the notification's sender as notification.object
. If you need to pass information along with the notification, you can use a different variant of postNotification:
that accepts a NSDictionary
, then you can access the dictionary as notification.userInfo
.
If you need to return values to the object that posted the messages, you'll have to send them back by sending messages to the poster (which you have access to as notification.object
). For instance:
- (void)methodOneNotification:(NSNotification *)notification {
AppDelegate *appDelegate = notification.object;
[appDelegate returningValue:1];
}
Here, obviously, AppDelegate would need to define and handle -(void)returningValue:(int)value
.
You'll need to keep the return value on the class instance. Of course, if you have multiple returns possible, you'll need to collect those in returningValue:
with an array. But at least you've skipped circular references.
The other way to solve this is with blocks. That would double the size of this answer, though. :) Bottom line, though: The delegate pattern is the wrong pattern for this problem. Luckily, the others are easy to pick up.