views:

984

answers:

3

My understanding is that protocols are like interfaces in other languages -- they declare expected methods -- while categories allow you to add new methods to existing types (perhaps even types you don't own.)

Why, then, does the iPhone SDK sometimes use categories for declaring delegate types? Normally I would expect all delegates to be typed id<MyDelegateProtocol> but there are many examples where this is not the case.

For example, see NSURLConnection. Its delegate is typed "id" and the 'contract' is declared as a category on NSObject (NSURLConnectionDelegate).

So: what's the motivation for using categories in these cases?

+11  A: 

Objective-C 2.0 introduced the @optional protocol directive, allowing you to declare certain protocol methods to be optional. Prior to Obj-C 2.0, categories were used to allow optional delegate methods (specifically, categories on NSObject, which are called informal protocols).

My guess is that most of the category-instead-of-protocol use in the iPhone SDK is a holdover from the equivalent Mac classes. For example, NSURLConnection exists in both the Mac and iPhone SDKs, so the code is likely shared. Since Apple hasn't yet gone through to change all of the Mac classes to use formal protocols, we're left with somewhat of an inconsistency.

Matt Ball
That was my guess but I didn't know for sure. Thanks!
Dave Peck
Expect to see the change to protocols come along quite soon, though. Now that optional protocol methods are allowed, using them will clean up the code quite a bit and get rid of a lot of now-unnecessary categories. (They're cool and all, but instead of tacking methods on NSObject at runtime, I think having a delegate implement a protocol is much cleaner, both conceptually and from a runtime perspective.)
Quinn Taylor
+4  A: 

Until the revision of Objective-C that was rolled out with OS X 10.5 and the iPhone SDK, called "Objective-C 2.0", one could only make optional protocols by using categories. In Objective-C 2.0, a new @optional keyword was added in protocols to mark which methods were optional (the remainder is implicitly required).

So I think what you see is a slight hold-over from the earlier days before the @optional keyword.

Edit: To answer the follow-up that appeared in the original question: The motivation for using a category on NSObject/id for an informal protocol is partly to document and group what methods the object may call in its datasource (or delegate or whatever), and to a lesser degree to avoid compiler warnings that you're calling methods that the compiler doesn't know will be present in the object that receives the call. Imagine being the one to implement the class which calls these datasource methods -- you would probably want to check that the method is present using [obj respondsToSelector: @selector(my:datasource:method:)] whenever you are interested in calling the my:datasource:method: method on the object obj.

harms
Makes sense -- thanks!
Dave Peck
+1  A: 

That's a legacy came from objective-c 1.0, which has no "optional protocol method".