Here's the situation. I'm writing a simple game and I had two main actors: GameController
and GridView
.
GridView
is aUIView
subclass displaying a grid with which the user interacts. It defines its custom delegate protocol (GridViewDelegate
) for handling callbacks such asgridView:didSelectTile
and others.GameController
is the game controller (duh!) which instantiate aGridView
and set itself as a delegate, therefore implementing theGridViewDelegate
protocol.
So far so good, then I decided to add HUD components on top of the grid (a score, a timer and other stuff). The most reasonable choice seemed to wrap such HUD components along with the grid into a new UIView
subclass called GameBoard
.
And here comes the design issue: I need the controller to talk to the GridView
and I think there's two reasonable options here.
Expose a
gridView
property and do something like[self.gameBoard.gridView doStuff];
Forward the invocation made to
GameBoard
directly toGridView
overriding theforwardInvocation:
method ofGameBoard
The first options looks like the most convenient, but I cannot get myself into liking it, due to the Law of Demeter.
So I decided to go for the second approach and do something like
// The GameBoard serves a proxy between the GameContoller and the GridView
- (void)forwardInvocation:(NSInvocation *)anInvocation {
if ([self.gridView respondsToSelector:anInvocation.selector]) {
[anInvocation invokeWithTarget:self.gridView];
} else {
[super forwardInvocation:anInvocation];
}
}
// This method is necessary for the above forwardInvocation to work
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
NSMethodSignature * signature = [super methodSignatureForSelector:aSelector];
if (!signature) {
signature = [self.gridView methodSignatureForSelector:aSelector];
}
return signature;
}
It works as expected, but I'd like to have a second opinion on my design choice.
I generally tend to avoid overusing of the dynamic features of Objective-C, but it looked like an elegant way to achieve my result fulfilling the Law of Demeter.