Building delegates like they do in UIKit

07 Dec 2011 1 min read

In UIKit, I often see delegate properties being declared as id and those delegates being able to access the performSelector method. In contrast, when I write custom protocols to be used as delegates, those delegates need to be of type NSObject to access performSelector.

Take this example protocol:

@protocol CustomDelegate

- (void)doAwesomeness;

@end

In order to access performSelector, I would need to declare the delegate as:

NSObject<CustomDelegate> *delegate;

rather than the more common:

id<CustomDelegate> delegate;

Is there some magic that Apple are sprinkling on their protocols that allows them access to greater functionality that I'm not?

Well, yes and that magic isn't even hidden just easy to miss - it's the NSObject protocol.

Confusingly, NSObject is both a protocol and a concrete type - the concrete type NSObject conforms to the protocol NSObject. Here we are talking about the protocol not the conrete type

Let's take UITextDelegate as our UIKit example and look it more closely. The first thing you will notice is that, unlike CustomDelegate, UITextDelegate inherits from the protocol NSObject:

@protocol UITextFieldDelegate <NSObject>

Any type that wants to conform UITextFieldDelegate must also conform to NSObject. NSObject is where performSelector is declared. So it is safe to call performSelector on that property as the compiler knows that UITextFieldDelegate is a specialised form of NSObject.

CustomDelegate doesn't enforce that a type that conforms to it must also conform to NSObject. The compiler cannot guarantee that any conforming type will implement performSelector, so it prevents potentially unsafe calls to performSelector on that property.

Updating CustomDelegate to inherit the NSObject protocol means that I can use id as the property type, allowing my protocols to feel more like those we get from UIKit.

What do you think? Let me know by getting in touch on Mastodon or Bluesky.