NSInvocation的使用

在ios直接調用某個對象的消息是方法有兩種:

一:performselector:withObject:

二:invocation

第一種方式比較簡單,能完成簡單的調用。但是對於>2個的參數或者有返回值的處理,那就需要做些額外工作才能搞定。那麼在這種情況下,我們就可以使用NSInvocation來進行這些相對複雜的操作

NSInvocation可以處理參數、返回值。會java的人都知道凡是操作,其實NSInvocation就相當於反射操作。

  1. //方法簽名類,需要被調用消息所屬的類AsynInvoke ,被調用的消息invokeMethod:  
  2. NSMethodSignature *sig= [[AsynInvoke class] instanceMethodSignatureForSelector:@selector(invokeMethod:)];  
  3. //根據方法簽名創建一個NSInvocation  
  4. NSInvocation *invocation=[NSInvocation invocationWithMethodSignature:sig];  
  5. //設置調用者也就是AsynInvoked的實例對象,在這裏我用self替代  
  6. [invocation setTarget:self];  
  7. //設置被調用的消息  
  8. [invocation setSelector:@selector(invokeMethod:)];  
  9. //如果此消息有參數需要傳入,那麼就需要按照如下方法進行參數設置,需要注意的是,atIndex的下標必須從2開始。原因爲:0 1 兩個參數已經被target 和selector佔用  
  10. NSInteger num=10;  
  11. [invocation setArgument:&num atIndex:2];  
  12. //retain 所有參數,防止參數被釋放dealloc  
  13. [invocation retainArguments];  
  14. //消息調用  
  15. [invocation invoke];  
  16. //如果調用的消息有返回值,那麼可進行以下處理  
  17.   
  18.   
  19.   
  20. //獲得返回值類型  
  21. const char *returnType = sig.methodReturnType;  
  22. //聲明返回值變量  
  23. id returnValue;  
  24. //如果沒有返回值,也就是消息聲明爲void,那麼returnValue=nil  
  25. if( !strcmp(returnType, @encode(void)) ){  
  26.     returnValue =  nil;  
  27. }  
  28. //如果返回值爲對象,那麼爲變量賦值  
  29. else if( !strcmp(returnType, @encode(id)) ){  
  30.     [invocation getReturnValue:&returnValue];  
  31. }  
  32. else{  
  33. //如果返回值爲普通類型NSInteger  BOOL  
  34.   
  35.     //返回值長度  
  36.     NSUInteger length = [sig methodReturnLength];  
  37.     //根據長度申請內存  
  38.     void *buffer = (void *)malloc(length);  
  39.     //爲變量賦值  
  40.     [invocation getReturnValue:buffer];  
  41.   
  42. //以下代碼爲參考:具體地址我忘記了,等我找到後補上,(很對不起原作者)  
  43. if( !strcmp(returnType, @encode(BOOL)) ) {  
  44.     returnValue = [NSNumber numberWithBool:*((BOOL*)buffer)];  
  45. }  
  46. else if( !strcmp(returnType, @encode(NSInteger)) ){  
  47.     returnValue = [NSNumber numberWithInteger:*((NSInteger*)buffer)];  
  48. }  
  49.     returnValue = [NSValue valueWithBytes:buffer objCType:returnType];  
  50. }  

 

 

調用步驟:

  1. - (NSString *) myMethod:(NSString *)param1 withParam2:(NSNumber *)param2{  
  2.       
  3.     NSString *result = @"Objective-C";  
  4.     NSLog(@"Param 1 = %@", param1);  
  5.     NSLog(@"Param 2 = %@", param2);  
  6.     return(result);  
  7. }  
  8.   
  9. - (void) invokeMyMethodDynamically {  
  10.     SEL selector = @selector(myMethod:withParam2:);  
  11.       
  12.     NSMethodSignature *methodSignature = [[self class] instanceMethodSignatureForSelector:selector];  
  13.       
  14.     NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];  
  15.       
  16.     [invocation setTarget:self];  
  17.       
  18.     [invocation setSelector:selector];  
  19.   
  20.     NSString *returnValue = nil;  
  21.     NSString *argument1 = @"First Parameter";  
  22.     NSNumber *argument2 = [NSNumber numberWithInt:102];  
  23.       
  24.     [invocation setArgument:&argument1 atIndex:2];  
  25.     [invocation setArgument:&argument2 atIndex:3];  
  26.     [invocation retainArguments];  
  27.     [invocation invoke];  
  28.     [invocation getReturnValue:&returnValue];  
  29.       
  30.     NSLog(@"Return Value = %@", returnValue);  
  31. }  
  32.   
  33.    

 

 

To do this, you need to follow these steps:
1. Form a SEL value using the name of the method and its parameter names (as
explained in Recipe 1.7).
2. Form a method signature of type NSMethodSignature out of your SEL value.
3. Form an invocation of type NSInvocation out of your method signature.
4. Tell the invocation what object you are targeting.
5. Tell the invocation what selector in that object you want to invoke.
6. Assign any arguments, one by one, to the invocation.
7. Invoke the method using the invocation object and demand a return value (if any).


發佈了36 篇原創文章 · 獲贊 0 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章