Could someone please advise me on best or practical way of creating a many to one relationship messaging system. I am new to Objective-C so if this something that I "should know" as an Obj-C developer, please feel free to point me in the right direction on tutorials/documentation.
Currently, I'm working on a Brick Breaker game to learn and get better at Obj-C/Cocos2D/Box2D. I am trying to create an internal messaging system in my BrickMgr class that holds instances of bricks (NSMutableArray). When a brick is destroyed, I want to notify my parent(BrickMgr) the score value of the brick, so that it can then decide how to use or communicate it to the heads-up-display(HUD).
From all the Googling/reading I've done, it seems like KVO or NSNotificationCenter would be the way to go, but all the examples I've read are one-to-many relationship. I am wondering could I do the opposite and use it in the form of many-to-1 relationship.
E.g.: In each instance of my Brick class, when the brick is destroyed I can do
//Brick class, when brick.state = BRICK_DESTROYED
[NSNotificationCenter defaultCenter] postNotificationName:BB_SCORE_CHANGED_NOTIFICATION object:self userInfo:nil];
and in my BrickManager class register my observer to listen to the postNotification
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onScoreChanged:) name:BB_SCORE_CHANGED_NOTIFICATION object:nil];
Please advise.
NSNotifications
are most useful for to-many relations, where they need to notify multiple objects of a change. Your implementation looks good (you'll also need to unregister for the notification inside dealloc
for instance).
As long as it's a to-one relation, you can also use delegates (since each object - brick - will need to notify 1 single object).
You could have for instance:
// Brick.h
@class Brick;
@protocol BrickDelegate <NSObject>
-(void)brickStateChanged:(Brick *)sender;
// .. some other methods
@end
@interface Brick : NSObject {
id<BrickDelegate> _delegate;
}
@property(nonatomic, assign) id<BrickDelegate> delegate;
@end
// Brick.m
@implementation Brick
@synthesize delegate=_delegate;
...
-(void)setState:(int)newState{
if(_state==newState) {
return;
}
_state=newState;
[self.delegate brickStateChanged:self];
}
...
@end
Somewhere in another class:
// in the init method for instance
_bricks = [[NSMutableArray alloc] init];
Brick *b = [[Brick alloc] init];
b.delegate = self;
[_brocks addObject:[b autorelease]];
-(void)brickStateChanged:(Brick *)sender {
// handle state changed for the brick object
}
-(void)dealloc{
// reset the delegates - just in case the Brick objects were retained by some other object as well
[_bricks enumerateObjectsUsingBlock:^(Brick *b, NSUInteger idx, BOOL *stop){
b.delegate = nil;
}];
[_bricks release];
[super dealloc];
}