This was something that came up at last night’s Cocoaheads so I thought I’d share my thoughts on it here. I’m way overdue for a post anyways.
Both delegates and blocks allow for callbacks, a way to allow an API user to provide custom logic to what is otherwise a black box. With the advent of blocks, there’s a temptation by some to use them everywhere. But as with anytime you have a new toy (ok, not so new in this case but newer), you must resist the temptation to stop using old stuff when is still better suited for the situation.
So, when do you use delegates? Delegates are for when there will be a closer, long term relationship between objects. There is usually a well defined interface for the delegate to follow. The delegate itself is probably maintaining state and consolidating logic for this purpose. From the point of view of the object using the delegate, it is a one-to-one relationship (the delegate might not actually be monogamous in this relationship and be a delegate to several objects). You can rely on one object to know how to handle these cases and expect some level of self consistency.
How about block callbacks? These are best suited for more ad hoc cases. Usually these blocks are called immediately or up to a few times in the not too distant future. An example of the former is having a block called on the elements in an array, after which, control is returned to the caller. For the latter, completion or progress handlers are typical examples, where you initiate some longer running process and want to specify behavior for certain events. The reason blocks are good for this situation is that they can capture the immediate context and use that in the custom code. This is also why blocks are less well suited for longer term relationships as they end up creating undesired or unintended dependencies that are harder to extricate.
The rules are not cut and dry but hopefully you’ll see that there’s a need for both. It’s both fortunate and unfortunate that blocks came into the Cocoa world as late as they did. While it did allow for the creation of some solid and clean use of delegates, it also allowed for some APIs which should have used blocks from the beginning (basically anything which takes a user-supplied context parameter). Hopefully Apple will clean these up over time but for your own APIs, be mindful of the differences.