Delegation without a protocol?


#1

I am new to iOS programming and have a silly question about delegation. I thought that for an object to be a delegate, it had to conform to a protocol.

But then I see something like:

connectionInProgress = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];

So we are saying that the RSSTableViewController will be a delegate of our NSURLConnection … but no sign of a connection protocol declaration here:

@interface RSSTableViewController : UITableViewController <NSXMLParserDelegate> {

Sorry if I missed something obvious … but I find myself confused.


#2

It’s actually not obvious and pretty confusing, so don’t worry about it.

Back in the day (pre-ObjC 2.0), protocols could only contain required methods. Therefore, in order to have a “delegate protocol” (in which some methods could optionally be implemented), we stuck categories onto NSObject (since everything derives from NSObject) in which the delegate methods were implemented to do nothing. If you wanted to implement a delegate method, you were technically just overriding an existing method from NSObject. We called these informal protocols.

Most classes these days have been updated so that they have a protocol for their delegate methods because now we can have optional methods in a protocol. There are two things to note about this situation:

  1. Not all classes have a formal protocol for their delegate objects. NSURLConnection is such a class. The compiler will never be able to warn you about setting an object as a delegate of an NSURLConnection because every object implements those delegate methods to do nothing.

  2. Declaring that a class conforms to a protocol (by placing in its interface) doesn’t actually do much. But, it does two (three if you see additional pointless note) things for you, the programmer, to help track down bugs though:

    i. When you say a class conforms to a protocol, and it has required methods, if you forget to implement one of those required methods (or you have a typo for that required method!), the compiler will WARN you.
    ii. Classes who have a delegate protocol of course have a delegate instance variable. The type of this instance variable will be:

id <SomeDelegateProtocol> delegate;

Therefore, when you attempt to assign an object as a delegate, the compiler will make a check for you. If the class of the delegate object does not have in its interface, the compiler will WARN you.

Note that in both situations, these are just warnings. Also note, if you hook up a delegate in IB, you don’t get any warnings (this is a compiler check). Therefore, you can completely leave out the protocol declarations for an interface and nothing bad will happen.

Also note that there is a method implemented by NSObject that allows you to ask, at runtime, whether or not an object conforms to a given protocol.

BOOL flag = [object conformsToProtocol:@protocol(SomeDelegateProtocol)];

If you (or a class you are using) uses this method, then you do need to include the protocol declaration in the interface. This is rare that you would use this. Typically, you ask an object if it respondsToSelector: on a message by message basis.


#3

Thanks, that helped!