2009-04-09 7 views
69

AVAudioPlayerのようなクラスを拡張したい場合、AVAudioPlayerDelegateに別のメソッドを追加するのに最適な方法は何ですか?私はそれのためのカテゴリーを作るのですか、それを拡張しますか?もし私がそれを拡張すれば、実際の代理人getter/setterを上書きする必要がありますか?どのようにプロトコルを拡張するのですか?以下は私にエラーObjective-Cでプロトコル/デリゲートを拡張する方法



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

@interface AudioTrack : AVAudioPlayer { 
} 
@end 

答えて

125

を与える別のプロトコルを実装したプロトコルを作成するための構文は次のような次のとおりです。

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

あなたができるOldProtocolとして型指定されたポインタにNewProtocolでメソッドを呼び出したい場合respondsToSelectorを呼び出して、次のいずれか

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

またはNSObjectのカテゴリーとしてのスタブ・メソッドを定義します:

@interface NSObject (NewProtocol) 
- (void)foo; 
@end 
@implementation NSObject (NewProtocol) 
- (void)foo 
{ 
} 
@end 
+0

別のプロトコルを実装するプロトコルを作成すると、「OldProtocol」メソッドが起動するようにするために必要なことはありますか? ?私のために私は新しいプロトコルを起動しているが、既存のものはもうなくなるから – dizy

+10

プロトコルはメソッドを持たず、メソッド定義を持っている。つまり、クラスがそのプロトコルに「準拠している」とみなされなければならない名前、引数、および戻り値の型を記述します。あなたのコメント/質問で、私はあなたが-setDelegate: – rpetrich

+0

で[super setDelegate:value]を呼ぶことを忘れていると賭けているのですが、新しいプロトコルのメソッドを公開していないこのアプローチを使って、私の返信をきれいに見てください – Kappe

11

プロトコルを覚えていますがコンパイルされ、アプリケーションへのコードを追加していない - それは唯一のプロトコルに「準拠」と見なされるためにあなたのクラスはメソッドを実装しなければならないという事実を強制します。これをうまく利用運転の全て同じ方法でクラスのグループを生成するために、次のようになります。あなたは、例えば<plays>プロトコルを作成することができるようになど、<printable>または<serialized>

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

そして準拠したクラス<plays>には、playtypeのメソッドを実装する必要があります。そうでなければ、コンパイラは警告を出しますが、とにかくクラスをコンパイルします。あなたのコードでは、オブジェクトが次のコードでプロトコルに準拠しているかどうかをチェックします:

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

実際には、クラスはクラスに新しいメソッドを動的に追加します。これらのメソッドは、セレクタとしてランタイムにグローバルにアクセス可能であり、@selector(foo)および[object foo:bar];

のような名前で呼び出すことができます。カテゴリの目的は、ソースコードを持たなくても特別な新しいコードをクラスに追加することですそのクラス。そこセキュリティ上の問題があることができ、あなたはクラスでメモリリークを作成することができ、など

あなたのケースでは、多分、別のファイルにNSObjectのカテゴリーとしてそれを置くAVAudioPlayerDelegate_TrackOps.m

#import "AVAudioPlayerDelegate.h" 
@implementation AVAudioPlayerDelegate (TrackOps) 

- (NSObject *) foo { 
    // do foo stuff; 
    return bar; 
} 

@end 

は、すべてのクラスがfooに応えます。 Fooはスタンドアローン方式のObjc_perform_selector(@selector(foo))でもかまいません。

ボトムライン:クラスにクイックメソッドを追加するためのカテゴリ、メソッド実装を実施するためのプロトコル、既存のクラスを特化するサブクラス(メンバー変数の追加や主要な新機能など)を使用します。カテゴリは、サブクラスが必要ではなく必要な場合にメソッドをオーバーライドするためにも使用できますが、通常、サブクラスを作成するクラスに機能を追加する場合に使用します。その他の例、アイデア、このトピックのその他の一般情報については、常にあります。Apple introduction to Objective-C

+0

カテゴリをプロトコルに追加する方法を詳しく教えてください。私は、あなたが書いた文法で何かが間違っていると思う。ありがとう – dizy

関連する問題