IOS中有一个类型是SEL
,它的作用很相似与函数指针,通过performSelector:withObject:
函数可以直接调用这个消息。但是perform相关的这些函数,有一个局限性,其参数数量不能超过2个,否则要做很麻烦的处理,与之相对,NSInvocation
也是一种消息调用的方法,并且它的参数没有限制。
NSInvocation对象只能使用其类方法来初始化,不能使用alloc/init方法。它执行调用之前,需要设置两个方法:
setSelector:
:用来设置selector;setArgument:atIndex:
用来为消息传递参数
看一下简单使用的代码:
invocation.h文件代码
#import <Foundation/Foundation.h>
@interface invocation : NSObject
-(void)invoker;
-(void)myLog;
@end
invocation.m文件代码
#import "invocation.h"
@implementation invocation
-(void)invoker{
SEL myMethod=@selector(myLog);
NSMethodSignature *sig=[NSNumber instanceMethodSignatureForSelector:@selector(init)];
NSInvocation* invocatin=[NSInvocation invocationWithMethodSignature:sig];
[invocatin setTarget:self];
[invocatin setSelector:myMethod];
[invocatin invoke];
}
-(void)myLog{
NSLog(@"myLog");
}
@end
main.m代码
#import <Foundation/Foundation.h>
#import "invocation.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
[[[invocation alloc] init] invoker];
}
return 0;
}
如果要传递参数给消息时,代码如下:只改动了invocation.m代码
#import "invocation.h"
@implementation invocation
-(void)invoker{
SEL myMethod=@selector(myLog:param:param:);
NSMethodSignature *sig=[[self class] instanceMethodSignatureForSelector:myMethod];
NSInvocation* invocatin=[NSInvocation invocationWithMethodSignature:sig];
[invocatin setTarget:self];
[invocatin setSelector:myMethod];
int a=1;
int b=2;
int c=3;
[invocatin setArgument:&a atIndex:2];
[invocatin setArgument:&b atIndex:3];
[invocatin setArgument:&c atIndex:4];
[invocatin invoke];
}
-(void)myLog:(int)a param:(int)b param:(int)c{
NSLog(@"myLog %d",a+b+c);
}
@end
上面代码中,setArgument
方法设置参数的Index 需要从2开始,因为前两个被selector和target占用。
NSInvocation对象,是可以有返回值的,然而这个返回值,并不是其所调用函数的返回值,需要我们手动设置:
[invocatin setReturnValue:&c];
int d;
[invocatin getReturnValue:&d];
NSLog(@"%d",d);
操作传递的都是地址。如果是OC对象,也是取地址。