One of the first patterns you encounter when you’re learning Cocoa is the way Apple’s view classes extend their functionality with delegates.
If Apple does it with their view classes, it must be a great idea for your view classes too, right?
The answer you’re looking for here is “no”.
Let’s play a game of 20 2 questions, shall we?
1. Is your view class (a) a general-purpose class, intended to be used by future clients in ways you can’t anticipate? Or is it (b) a very specific class used in a very specific, single way?
2. Do you have (a) two or more classes serving as delegates for your view? Or is the delegate (b) always the same class, used in exactly the same way, to the point where you’re not even bothering with respondsToSelector:
checks?
If the answers to both questions are (b), then you know what using the delegate pattern buys you for connecting your view class to its “delegate”? That’s right, nothing. And you know what it causes for the people who come in later to maintain your class? A big headache, right again!
For one, they have to spend the time investigating what classes actually serve as the delegate of your view class. They may need to run the app, get it into a variety of hard-to-reproduce states, just to be sure. Certainly, this might not be that big of a deal for one class. But in a large codebase where this “pattern” has been used repeatedly, it can bog things down.
For two, it means they can’t entirely rely on the automated refactoring tools when they want to make changes to the delegate classes. Because delegates are of type id
, right? That’s the pattern. So that bogs things down, too.
Let me spell it out: if you have a view subclass (or any class, really) that needs functionality from an associated class, add a typed reference to that associated class. Don’t add an untyped “delegate” reference.
By all that is holy (donuts, CDs, bowling balls, etc.), don’t create your own DeleGate scandal.
And stay tuned for my next post, where I rant for twenty pages about bindings misuse.
I disagree. The advantage of the delegate pattern is not just code reuse, it is also a great way to maintain separation between the view and the controller. Using a typed reference weakens this separation.
I agree that untyped delegates are bad; a protocol should be used. The protocol should conform to the NSObject protocol and should make use of @required. The delegate should conform to the protocol. This approach means the compiler can let you know when changes go wrong (and you can take a shortcut and skip respondsToSelector: if the delegate method has been marked as @required).
I agree that there is a danger of over engineering, but I think the cost of the delegate pattern is worth paying to maintain proper separation between the view and controller.