NSInvocation慢慢整理

来源:互联网 发布:黄子韬小精灵软件 编辑:程序博客网 时间:2024/06/06 04:44

在 iOS中可以直接调用某个对象的消息方式有两种:
一种是performSelector:withObject;
再一种就是NSInvocation。

第一种方式比较简单,能完成简单的调用。但是对于>2个的参数或者有返回值的处理,那就需要做些额外工作才能搞定。那么在这种情况下,我们就可以使用NSInvocation来进行这些相对复杂的操作。

NSInvocation

IOS中有一个类型是SEL,它的作用很相似与函数指针,通过performSelector:withObject:函数可以直接调用这个消息。但是perform相关的这些函数,有一个局限性,其参数数量不能超过2个,否则要做很麻烦的处理,与之相对,NSInvocation也是一种消息调用的方法,并且它的参数没有限制。这两种直接调用对象消息的方法,在IOS4.0之后,大多被block结构所取代,只有在很老的兼容性系统中才会使用,简单用法总结如下:

一、初始化与调用

在官方文档中有明确说明,NSInvocation对象只能使用其类方法来初始化,不可使用alloc/init方法。它执行调用之前,需要设置两个方法:setSelector: 和setArgument:atIndex:

1. 无参数无返回值

- (void)viewDidLoad {    [super viewDidLoad];    SEL myMethod = @selector(myLog);    //创建一个函数签名,这个签名可以是任意的,但需要注意,签名函数的参数数量要和调用的一致。    // 这个方法在NSObject有两个方法生成签名    NSMethodSignature * sig  = [NSNumber instanceMethodSignatureForSelector:@selector(init)];    //通过签名初始化    NSInvocation * invocatin = [NSInvocation invocationWithMethodSignature:sig];    //设置target    [invocatin setTarget:self];    //设置selecteor    [invocatin setSelector:myMethod];    //消息调用    [invocatin invoke];}-(void)myLog{    NSLog(@"MyLog");}

注意:签名函数的参数数量要和调用函数的一致。测试后发现,当签名函数参数数量大于被调函数时,也是没有问题的。

2. 多参数无返回值

调用多参数的方法,我们可以这样写:

- (void)viewDidLoad {    [super viewDidLoad];    SEL myMethod = @selector(myLog:parm:parm:);    NSMethodSignature * sig  = [[self class] instanceMethodSignatureForSelector:myMethod];    NSInvocation * invocatin = [NSInvocation invocationWithMethodSignature:sig];    [invocatin setTarget:self];    [invocatin setSelector:myMethod2];    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 retainArguments];    [invocatin invoke];}-(void)myLog:(int)a parm:(int)b parm:(int)c{    NSLog(@"MyLog%d:%d:%d",a,b,c);}

注意:1、这里设置参数的Index 需要从2开始,因为前两个被selector和target占用。可以注意到- (void)retainArguments;这个方法,它会将传入的所有参数以及target都retain一遍。

3. 有返回值

NSInvocation对象,是可以有返回值的,然而这个返回值,并不是其所调用函数的返回值,需要我们手动设置:

- (void)viewDidLoad {    [super viewDidLoad];    SEL myMethod = @selector(myLog:parm:parm:);    NSMethodSignature * sig  = [[self class] instanceMethodSignatureForSelector:myMethod];    NSInvocation * invocatin = [NSInvocation invocationWithMethodSignature:sig];    [invocatin setTarget:self];    [invocatin setSelector:myMethod2];    ViewController * view = self;     int a=1;    int b=2;    int c=3;    [invocatin setArgument:&view atIndex:0];    [invocatin setArgument:&myMethod2 atIndex:1];    [invocatin setArgument:&a atIndex:2];    [invocatin setArgument:&b atIndex:3];    [invocatin setArgument:&c atIndex:4];    [invocatin retainArguments];    //我们将c的值设置为返回值    [invocatin setReturnValue:&c];    int d;    //取这个返回值    [invocatin getReturnValue:&d];    NSLog(@"%d",d);}-(int)myLog:(int)a parm:(int)b parm:(int)c{    NSLog(@"MyLog%d:%d:%d",a,b,c);    return a+b+c;}

注意:这里的操作传递的都是地址。如果是OC对象,也是取地址。

0 0
原创粉丝点击