(1)用法
NSInvocation是調用函數的另一種方式,它將調用者,函數名,參數封裝到一個對象,然后通過一個invoke函數來執行被調用的函數,其思想就是命令者模式,將請求封裝成對象。
例如,有這樣一個類:
@implementation CA
-(int)AddA:(int)a andB:(int)b
{
return a + b;
}
@end
一般調用函數的方式是:
CA *ca = [CA new];
int result = [ca AddA:2 andB:3];
或者用performSelector,但是后者只能有一個參數,所以對於有多個參數的情況,就可以用NSInvocation來調用。
示例代碼: CA *ca = [CA new]; NSMethodSignature *sig= [[CA class] instanceMethodSignatureForSelector:@selector(AddA:andB:)]; //根據selector得到一個簽名對象 NSInvocation *invocation=[NSInvocation invocationWithMethodSignature:sig];//根據該簽名對象創建一個NSInvocation對象 invocation.target = ca;//指定調用函數的對象 invocation.selector = @selector(AddA:andB:);//指定要調用的函數名 int a = 20; int b = 30; [invocation setArgument:&a atIndex:2];//指定參數,以指針方式,並且第一個參數的起始index是2,因為index為1,2的分別是self和selector [invocation setArgument:&b atIndex:3]; [invocation retainArguments];//因為NSInvocation不會自己去retain參數,因此需要用戶去retain,當然本例中其實沒必要 [invocation invoke]; //獲取返回值的過程略有點復雜,需要根據起類型長度分配空間,然后轉為對象 //如果是int,BOOL等簡單類型,返回的對象是NSNumber //如果是其他類型的對象,返回的對象是NSValue //判斷返回值類型,用strcmp(returnType, @encode(NSInteger)) const char *returnType = sig.methodReturnType; id returnValue; NSUInteger length = [sig methodReturnLength]; void *buffer = (void *)malloc(length); [invocation getReturnValue:buffer]; returnValue = [NSNumber numberWithInteger:*((NSInteger*)buffer)];//int的情況 //returnValue = [NSNumber numberWithBool:*((BOOL*)buffer)]; //bool 的情況 //returnValue = [NSValue valueWithBytes:buffer objCType:returnType];// 其他類型的情況 int result = [returnValue intValue]; NSLog(@"result=%d",result);
(2) 用到NSInvocation的一些場合
[NSTimer scheduledTimerWithTimeInterval:0.1 invocation:invocation repeats:YES]
NSInvocationOperation //它是NSOperation的派生類,用NSInvoation來初始化
(void)forwardInvocation:(NSInvocation *)anInvocation
這個函數與forwardTargetWithSelector類似,當某個對象收到一個selector消息,但該對象沒有實現該selector,且實現forwardInvocation,那么系統會構造一個NSInvocation對象,並調用forwardInvocation,這樣在函數里面,用戶就可以用[invocation invokeWithTarget:friend];來讓另一個對象來執行這個selector.
要實現這個函數,還必須實現methodSignatureForSelector,因為這個anInvocation是系統構造的,構造這個對象需要有簽名對象,這個對象必須由用戶提供。所以這個函數用起來比forwardingTargetForSelector麻煩
另外,由於使用forwardInvocation可以使得一個對象將它沒有實現的方法轉發給其他對象,因此可以變相的實現多繼承。
參考鏈接:http://www.cnblogs.com/pengyingh/articles/2359199.html