Objective-C Protocols within Protocols

Posted by LucasTizma on Stack Overflow See other posts from Stack Overflow or by LucasTizma
Published on 2009-10-30T16:44:57Z Indexed on 2010/03/11 21:29 UTC
Read the original article Hit count: 472

I recently began trying my hand at using protocols in my Objective-C development as an (obvious) means of delegating tasks more appropriately among my classes. I completely understand the basic notion of protocols and how they work. However, I came across a roadblock when trying to create a custom protocol that in turn implements another protocol. I since discovered the solution, but I am curious why the following DOES NOT work:

@protocol STPickerViewDelegate < UIPickerViewDelegate >

- ( void )customCallback;

@end

@interface STPickerView : UIPickerView
{
    id < STPickerViewDelegate > delegate;
}

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

@end

Then in a view controller, which conforms to STPickerViewDelegate:

STPickerView * pickerView = [ [ STPickerView alloc ] init ];
pickerView.delegate = self;

- ( void )customCallback
{
    ...
}

- ( NSString * )pickerView:( UIPickerView * )pickerView titleForRow:( NSInteger )row forComponent:( NSInteger )component
{
    ...
}

The problem was that pickerView:titleForRow:forComponent: was never being called. On the other hand, customCallback was being called just fine, which isn't too surprising. I don't understand why STPickerViewDelegate, which itself conforms to UIPickerViewDelegate, does not notify my view controller when events from UIPickerViewDelegate are supposed to occur. Per my understanding of Apple's documentation, if a protocol (A) itself conforms to another protocol (B), then a class (C) that conforms to the first protocol (A) must also conform to the second protocol (B), which is exactly the behavior I want and expected.

What I ended up doing was removing the id< STPickerViewDelegate > delegate property from STViewPicker and instead doing something like the following in my STViewPicker implementation where I want to evoke customCallback:

if ( [ self.delegate respondsToSelector:@selector( customCallback ) ] )
{
    [ self.delegate performSelector:@selector( customCallback ) ];
}

This works just fine, but I really am puzzled as to why my original approach did not work.

© Stack Overflow or respective owner

Related posts about objective-c

Related posts about protocols