views:

2176

answers:

2

If i want to extend a class like AVAudioPlayer, whats the best way to also add another method to AVAudioPlayerDelegate ?. Do I make a category for it, do I extend it? If I extend it do I then also have to make sure to overwrite the actual delegate getter/setter ? How would I extend the protocol ? The following gives me errors



@protocol AudioTrackDelegate : AVAudioPlayerDelegate {
    - (void)foo;
}
@end

@interface AudioTrack : AVAudioPlayer {
}
@end
+7  A: 

The syntax for creating a protocol that implements another protocol is as such:

@protocol NewProtocol <OldProtocol>
- (void)foo;
@end

If you want to call a method in NewProtocol on a pointer typed as OldProtocol you can either call respondsToSelector:

if ([object respondsToSelector:@selector(foo)])
    [(id)object foo];

Or define stub methods as a category on NSObject:

@interface NSObject (NewProtocol)
- (void)foo;
@end
@implementation NSObject (NewProtocol)
- (void)foo
{
}
@end
rpetrich
If I create a protocol that implements another protocol... Is there anything else I need to do to make sure the 'OldProtocol' methods get fired ? because for me i'm getting the new protocol firing but all the existing ones aren't any longer
dizy
A protocols doesn't have methods, it has method definitions; that is, it describes the name, arguments and return types that a class must have to be deemed "conforming" to said protocol. By your comment/question I'm betting you are forgetting to call [super setDelegate:value] in your -setDelegate:
rpetrich
that was it... thanks!!!
dizy
+3  A: 

Remember A protocol adds no code to the compiled app -- it only enforces the fact that your class must implement the methods to be considered " conforming" to the protocol. A good use of this would be to generate a group of classes with all the same way of operating: or , etc.
So you could create a category for iinstance:

@protocol plays
-(void) play;
-(NSString*)type;
@end

and then a class that conforms to MUST implement the play and type methods. If it doesn't the compiler issues a warning but compiles the class anyway. In your code you check:

if ( [obj conformsTo: @protocol(plays)] ) [ obj play];

A category actually adds new methods dynamically to your class. These methods are globally accessible to the runtime as selectors and can be called by name as in @selector(foo) and [object foo:bar];

The category Idea is to add special new code to a class even if you don't have the source code for that class. So of course there may be security problems and you could create memory leaks in classes, etc.

In your case maybe: in a separate file AVAudioPlayerDelegate_TrackOps.m

#import "AVAudioPlayerDelegate.h"
@implementation AVAudioPlayerDelegate (TrackOps)
{
- foo {
  // do foo stuff;
  return bar;
}
@end

Putting it as a category of NSObject makes all classes respond to foo. Foo can be a stand alone method Objc_perform_selector(@selector(foo)) as well.

Bottom Line: use a category to add a quick method to a class, protocols for enforcing method implementations, and sublcasses to specialize existing classes like adding member variables or major new functionality. categories can also be used to override a method or two when a subclass is not needed and wanted, but usually if you want to add functionality to a class you make a subclass. read the Objc book and do some examples.

http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Introduction/introObjectiveC.html

thanks, that was a good explanation
dizy
Can you please elaborate on how to add a category to a protocol ? I think somethings wrong with the syntax of what you wrote. thanks
dizy