NSInvocation

在寫程式的時候, 常常會有需要呼叫好幾個method, 然後在時間上有所需別; 最常遇到的都是希望Layout改變完成之後再去執行下一步動作, 如果是一堆layout animation, 就會很常使用到delay去做一些時間差的區別.

can do it this way
1
2
3
4
5
6
7
- (void)currentMehtod {  SEL action2 = @selector(action2:);  [object performSelector:action2 withObject:data afterDelay:1.f];  /** …  * do somethig after …  **/ } 

一開始使用的時候覺得還好, 但是慢慢的發現如果我的method一開始寫的時候帶入多個參數, 如果用上面的方式, 就要改寫本來的method, 這樣又得花時間, 而且可能最後都是帶入NSDictionary的物件, 在把需要的資料拉出來, 常常會把map的key打錯又多花很多時間在debug.

在StackOverflow上查了參數數量的問題, 沒想到還真的有一個很棒的解法, 就是 NSInvocation.

NSInvocation

NSInvocation的使用有一個地方要特別注意, invocation不能使用 allocinit來建立實體, 只能使用invocationWithMethodSignature:來建立object.

object的method
1
2
3
- (void)actionInvokeArgument1:(NSInteger)arg1 arg2:(NSNumber *)arg2 {  NSLog(@"action: arg1 + arg2=%d", arg1 + [arg2 integerValue]); } 

使用Invocation, mehtod所帶入的參數也不用都轉成object, int、BOOL…etc.都可以使用

建立一個NSInvocation實體
1
2
3
SEL mySelector = @selector(actionInvokeArgument1:arg2:); NSMethodSignature* signature1 = [self methodSignatureForSelector:mySelector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature1]; 

我們先使用NSObject的instance mehtod(也可以使用Class mehtod, 依照個人使用習慣), 先取得一個NSMethodSignature物件, 並建立一個NSInvocation.

NSMethodSignature的numberOfArguments最小值是2; 0跟1是給預設的隱藏參數使用(self & _cmd). 從2開始才是method-spec使用.

這時取得的invocation只有簡單的method可帶入的argument數量, 在正式調用之前你還需要設定targetselector.

設定invocation並調用
1
2
3
4
5
6
7
[invocation setTarget:self]; [invocation setSelector:mySelector]; NSInteger arg1 = 1; NSNumber* arg2 = @2; [invocation setArgument:&arg1 atIndex:2]; [invocation setArgument:&arg2 atIndex:3]; [invocation invoke]; 

使用NSInvocation設定參數時, index要從2開始.

取得回傳值
1
2
3
NSInteger retVal; [invocation getReturnValue:&retVal]; NSLog(@"%d", retVal); 

如果要延遲的話可以這樣使用

delay invoke
1
[invocation performSelector:@selector(invoke) withObject:nil afterDelay:1];

要注意的是, 如果會需要取得回傳值, 可能不適合使用delay的方式~

你可能感兴趣的:(ios)