Objective-c-protocols

提供:Dev Guides
移動先:案内検索

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のインスタンスは、インターフェイスで特に宣言されたメソッドに応答するだけでなく、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プロパティタイプを使用する必要があります。