一、概述
在 iOS中可以直接調用 某個對象的消息 方式有2種
還有一種方式就是使用NSInvocation進行動態運行時的消息分發,動態的執行方法,相信大家一定經常使用NSObject類提供的performSelector系列方法,在這裏就不再對此進行描述了,今天主要是分享一下使用NSInvocation動態執行方法。
二、NSInvocation的使用
1、執行類方法
demo代碼如下:
- - (void)testClassMethod{
- NSString *string = nil;
- //初始化NSMethodSignature對象
- NSMethodSignature *sig = [NSString methodSignatureForSelector:@selector(stringWithString:)];
- //初始化NSInvocation對象
- NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig];
- //設置執行目標對象
- [invocation setTarget:[NSString class]];
- //設置執行的selector
- [invocation setSelector:@selector(stringWithString:)];
- //設置參數
- NSString *argString = @"test method";
- [invocation setArgument:&argString atIndex:2];
- //執行方法
- [invocation retainArguments];
- [invocation invoke];
- //獲取返回值
- [invocation getReturnValue:&string];
- NSLog(@"執行結果 ====%@",string);
- }
2、執行實例方法
- - (void)testInstanceMethod{
- NSString *string = [NSString stringWithFormat:@"我是一個string"];
- NSLog(@"1=%@",string);
- SEL subStringSel = @selector(substringFromIndex:);
- //初始化NSMethodSignature對象
- NSMethodSignature *methodSignature = [[NSString class] instanceMethodSignatureForSelector:subStringSel];
- //初始化NSInvocation對象
- NSInvocation *myInvocation = [NSInvocation invocationWithMethodSignature:methodSignature];
- //設置target
- [myInvocation setTarget:string];
- //設置selector
- [myInvocation setSelector:subStringSel];
- //設置參數
- int arg1 = 2;
- [myInvocation setArgument:&arg1 atIndex:2];//參數從2開始,index 爲0表示target,1爲_cmd
- //獲取結果
- NSString *resultString = nil;
- [myInvocation invoke];
- [myInvocation getReturnValue:&resultString];
- NSLog(@"2=%@",resultString);
- }
如果要調用的方法有多個參數,可以使用如下方法:
SEL theSelector = @selector(yourMethodWithString:number:)
NSMethodSignature * sig = [self methodSignatureForSelector:theSelector];
NSInvocation * theInvocation = [NSInvocation
invocationWithMethodSignature:sig];
[theInvocation setTarget:self];
[theInvocation setSelector:theSelector];
NSString *firstArgument = [NSString stringWithString:@"Test"];
NSNumber *secondArgument = [NSNumber numberWithInt:2];
[theInvocation setArgument:&firstArgument atIndex:2];
[theInvocation setArgument:&secondArgument atIndex:3];
[theInvocation retainArguments];
比較麻煩是不是,不如把所有參數打開到NSArray或NSDictionary,然後使用一個參數調用
另外,也可以考慮使用Grand Central Dispatch,Block會自動處理參數的retain和release,多個參數沒有任何問題
iPhone: NSTimer and that thing called userInfo
Tuesday, May 12, 2009
- - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
- UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
- UILabel *cellLabel = (UILabel *)[newCell.contentView viewWithTag:1];
- [newCell setSelected:YES animated:YES];
- NSMutableDictionary *myDictionary = [[NSMutableDictionary alloc] init];
- [myDictionary setObject:tableView forKey:@"table"];
- [myDictionary setObject:indexPath forKey:@"indexPath"];
- // The colon after the onTimer allows for the argument
- [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(onTimer:) userInfo:myDictionary repeats:NO];
- [myDictionary release];
- }
So the onTimer method will get called after .5 seconds and it's being sent the userInfo object containing that NSMutableDictionary. Now to use that...
- - (void)onTimer:(NSTimer *)timer {
- NSLog(@"--- %@", [timer userInfo] );
- [[[timer userInfo] objectForKey:@"table"] deselectRowAtIndexPath:[[timer userInfo] objectForKey:@"indexPath"] animated:YES];
- // I have a reference to the tableView so I can do this below
- // but to show how the keys work, the call above these works
- //[table deselectRowAtIndexPath:[[timer userInfo] objectForKey:@"indexPath"] animated:YES];
- }
- [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:@selector(handleTimer:) userInfo:@"參數" repeats:YES];
- 用的時候只要在下面函數裏調用強制轉換的userinfo就行,
- -(void)handleTimer:(NSTimer*)timer
- {
- //這裏使用(NSString *)[timer userInfo]
- }