Objective-Cプロトコル

Objective-Cを使用すると、特定の状況で使用されると予想されるメソッドを宣言するプロトコルを定義できます。プロトコルは、プロトコルに準拠したクラスで実装されます。

簡単な例は、ネットワークURL処理クラスです。これには、ネットワークURLフェッチ操作が終了すると、呼び出し元のクラスを通知するprocessCompletedデリゲートメソッドなどのメソッドを持つプロトコルが含まれます。

プロトコルの構文を以下に示します。

@protocol ProtocolName
@required
// list of required methods
@optional
// list of optional methods
@end

キーワードの下のメソッド @required プロトコルと以下のメソッドに準拠するクラスに実装する必要があります @optional キーワードはオプションで実装できます。

プロトコルに準拠するクラスの構文は次のとおりです

@interface MyClass : NSObject <MyProtocol>
...
@end

これは、MyClassのすべてのインスタンスが、インターフェイスで具体的に宣言されたメソッドに応答するだけでなく、MyClassがMyProtocolで必要なメソッドの実装も提供することを意味します。クラスインターフェイスでプロトコルメソッドを再宣言する必要はありません。プロトコルの採用で十分です。

複数のプロトコルを採用するクラスが必要な場合は、それらをコンマ区切りのリストとして指定できます。プロトコルを実装する呼び出し元オブジェクトの参照を保持するデリゲートオブジェクトがあります。

以下に例を示します。

#import <Foundation/Foundation.h>

@protocol PrintProtocolDelegate
- (void)processCompleted;

@end

@interface PrintClass :NSObject {
   id delegate;
}

- (void) printDetails;
- (void) setDelegate:(id)newDelegate;
@end

@implementation PrintClass
- (void)printDetails {
   NSLog(@"Printing Details");
   [delegate processCompleted];
}

- (void) setDelegate:(id)newDelegate {
   delegate = newDelegate;
}

@end

@interface SampleClass:NSObject<PrintProtocolDelegate>
- (void)startAction;

@end

@implementation SampleClass
- (void)startAction {
   PrintClass *printClass = [[PrintClass alloc]init];
   [printClass setDelegate:self];
   [printClass printDetails];
}

-(void)processCompleted {
   NSLog(@"Printing Process Completed");
}

@end

int main(int argc, const char * argv[]) {
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   SampleClass *sampleClass = [[SampleClass alloc]init];
   [sampleClass startAction];
   [pool drain];
   return 0;
}

プログラムをコンパイルして実行すると、次の結果が得られます。

2013-09-22 21:15:50.362 Protocols[275:303] Printing Details
2013-09-22 21:15:50.364 Protocols[275:303] Printing Process Completed

上記の例では、delgateメソッドがどのように呼び出されて実行されるかを見てきました。startActionで始まり、プロセスが完了すると、デリゲートメソッドprocessCompletedが呼び出され、操作が完了したことを通知します。

iOSまたはMacアプリでは、デリゲートなしでプログラムを実装することは決してありません。したがって、デリゲートの使用法を理解することが重要です。デリゲートオブジェクトは、メモリリークを回避するために、unsafe_unretainedプロパティタイプを使用する必要があります。