@protocol 是Obj-c 裡的一個關鍵字,直到@end關鍵字做結束,通常宣告在 .h 檔置於 @interface 之上,用法如下:
//aaa.h
@protocol myDelegation <NSObject> @required -(void)delegationPrint; @optional -(int)delegationLog:(int) iVal; @end @interface aaa <NSObject>在 aaa.h 宣告了一個叫做 myDelegation 的 protocol(協定) 出來並定義兩個方法 delegationPrint 以及 delegationLog:@property (weak, nonatomic) id <myDelegation> delegate;-(void) someMethod;-(void)anotherMethod:(NSString *)str@end
其中 delegationPrint 屬於 @require,表示若有其他類別採納了 myDelegation 這個protocol則"一定"要實現 delegationPrint 方法,否則編譯器會出現警告,反之 @option 則可以不實現。
再來宣告並讓編譯器自動合成一個 "採納 myDelegation" 的泛型物件叫做 delegate,且屬性為 weak及nonatomic 其中 weak 為必要,避免物件相互持有無法釋放造成 memory leak。
**採納myDelegation的泛型物件名稱為增加閱讀性,一般都固定名稱為 delegate,不建議採取其他名稱。
**唯有採納 myDelegation 的物件可以呼叫 @protocol 所定義的方法(method)。
程式流程怎麼跑用 log 來看最清楚不過了,所以在每個 Method 都加了 NSLog 方便大家做 tracking.
假設今天有個類別 bbb 採納了 aaa 的 protocol 則程式片段應如下。
//aaa.m
-(void) someMethod { //確保 delegate 不為空且可回應 delegatePrint Method if(self.delegate != nil && [self.delegate delegatePrint]){ NSLog(@"aaa.m someMethod exec"); [self.delegate delegatePrint]; } } -(void)anotherMethod:(NSString *)str { if(self.delegate != nil && [self.delegate delegateLog:]){ NSLog(@"aaa.m anotherMethod exec"); NSLog(@"str = %@ and return = %d",str, [self.delegate delegateLog:123]); } }// bbb.h
#import "aaa.h" @interface bbb:UIVierController <myDelegation> @end//bbb.m
程式執行的結果輸出如下@implementation ViewController-(void)viewDidLoad {aaa *myAAA = [aaa new];myAAA.delegate = self;[myAAA someMethod];[myAAA anotherMethod:@"Hello World!"];}-(void)delegationPrint{ NSLog(@" bbb.m delegationPrint exec"); } -(int)delegationLog:(int) iVal{ NSLog(@"bbb.m delegationLog exec"); NSLog(@"bbb.m delegationLog: %d",iVal); return iVal*10; }@end
aaa.m someMethod exec
bbb.m delegationPrint exec
aaa.m anotherMethod exec
bbb.m delegationLog exec
bbb.m delegationLog:123
str = HelloWorld! and return = 1230
以上程式碼片段是人腦 coding + 人腦 compiler,若是有錯誤的地方還請大家指正。
沒有留言:
張貼留言