Benedict's Soapbox About Me Selected Work

6 February 2011Adding Delegate Methods for an Objective-C Subclass (Extending a Protocol)

Delegation is a very common design pattern in Cocoa, AppKit and UIKit. Delegation provides many of the benefits of subclassing but without the pain and hassle that subclassing often involves. When delegation cannot provide the desired results subclassing can still provide a solution. Of course, the subclass can still use delegation to aid reuse.

Delegate properties general have the form:

@property(nonatomic, assign) id<UIScrollViewDelegate> delegate;

UIScrollViewDelegate is a protocol that describes the delegate methods that the object supports. When a subclasses provides additional delegate methods the protocol type should be changed to include the additional methods. This is achieved by ‘subclassing’ the delegate protocol. Here’s how to do it:

 

1. Define a new protocol that incorporate the existing protocol and defines the new delegate methods:

@protocol UITableViewDelegate <UIScrollViewDelegate>
@optional
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
...
@end

(Apples delegate protocols incorporate the NSObject protocol. The NSObject protocol defines respondsToSelector: which is used to determine if a delegate implements  method).

2. In the interface redefine the delegate property to use the new protocol:

@property(nonatomic, assign) id<UITableViewDelegate> delegate;

Redefining a superclasses property can be dangerous. If the type of the redefined property does not fulfil the requirements of the superclasses property then the superclass may attempt to perform invalid actions on the object. In this situation it is not a problem as we are redefining the property to be stricter than the superclass.

3. In the implementation tell the compiler that the delegate property will be provided at run time:

@dynamic delegate;

At runtime the property will be provided by the superclass.

 

That’s it! Some things to bare in mind when working with protocols:

  • Protocols should be defined in the header file of the class that uses them. Forward declarations will be required to keep the compiler happy. If the protocol is defined first then a forward declaration to the class will be needed before the protocol definition, if the class is defined first then a forward declaration to the protocol will be needed before the class definition.
  • Before invoking a delegate method check that the delegate implements the method by calling respondsToSelector:. Eg:

    if ((self.delegate respondsToSelector:@selector(tableView:willDisplayCell:forRowAtIndexPath:))
    {
    	[self.delegate tableView:self willDisplayCell:cell forRowAtIndexPath:indexPath];
    }
    

  • Be sure to include which protocols an object supports in its interface definition. (Protocol adherence can be stated in categories.)

2 Comments

Make a Comment

:

:



Timeline