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?
Protocol is a set of methods (either optional or required) that would be implemented by the class which conforms to that protocol. While, delegate is the reference to that class which conforms to that protocol and will adhere to implement methods defined in protocol. Have a look at this Apple doc for more detail.
You don't have to use protocols...but you should if you want to keep things flexible. Delegation is in essence asking someone else to do something for you. If you enforce a contract, then its more likely they will do it for you.
Objective-C allows you to define protocols, which declare the methods expected to be used for a particular situation. This chapter describes the syntax to define a formal protocol, and explains how to mark a class interface as conforming to a protocol, which means that the class must implement the required methods.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With