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.)
OMG! This is exactly what I was looking for. Not only the extending a delegate portion but on the actual UIScrollView as well. iOS 5 broke passing the touch events from the UIScrollView to the main view through the responder chain. Instead of using NextResponder I extended the UIScrollViewDelegate to include new protocol methods to accept them.
PERFECT PERFECT PERFECT.
Hi, i am trying to overwrite the NSURLConnection Delegate but i dont know where to start, can please give some more kind of informations and a little bit sample code? I want to extend the connectionDidFinishLoading delegate to see if the JSON-String i am becoming back got some error reporting for the user and it seems to me the best way to extend the delegate. It is even possible?