IOS NSInvocation应用与理解

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

一、初始化与调用

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

- (void)viewDidLoad {
    [super viewDidLoad];
    SEL myMethod = @selector(myLog);
    //创建一个函数签名,这个签名可以是任意的,但需要注意,签名函数的参数数量要和调用的一致。
    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");
}

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

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

- (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 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)viewDidLoad {
    [super viewDidLoad];
    SEL myMethod = @selector(myLog:parm:parm:);
    SEL myMethod2 = @selector(myLog);
    NSMethodSignature * sig  = [[self class] instanceMethodSignatureForSelector:myMethod];
    NSInvocation * invocatin = [NSInvocation invocationWithMethodSignature:sig];
    ViewController * view = self;
    [invocatin setArgument:&view atIndex:0];
    [invocatin setArgument:&myMethod2 atIndex:1];
    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);
}

2、这里的传参方式必须是传递参数地址。

二、NSInvocation的返回值

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对象,也是取地址。

三、关于内存

可以注意到- (void)retainArguments;这个方法,它会将传入的所有参数以及target都retain一遍。

时间: 2024-10-23 21:15:43

IOS NSInvocation应用与理解的相关文章

iOS关于代理的理解

直接上3个图,不知道说的对不对,欢迎大神指点 iOS关于代理的理解

IOS NSInvocation用法简介

[摘要]在 iOS中可以直接调用某个对象的消息方式有两种,其中一种就是NSInvocation,本文介绍IOS NSInvocation用法,并提供简单的示例代码供参考. 在 iOS中可以直接调用某个对象的消息方式有两种: 一种是performSelector:withObject: 再一种就是NSInvocation. 第一种方式比较简单,能完成简单的调用.但是对于>2个的参数或者有返回值的处理,那就需要做些额外工作才能搞定.那么在这种情况下,我们就可以使用NSInvocation来进行这些相

iOS开发:深入理解GCD 第一篇

最近把其他书籍都放下了,主要是在研究GCD.如果是为了工作,以我以前所学的GCD.NSOperation等知识已经足够用了,但学习并不仅仅知识满足于用它,要知其然.并且知其所以然,这样才可以不断的提高自身技术水平. 本文主要参考http://www.raywenderlich.com/60749/grand-central-dispatch-in-depth-part-1 和 <iOS与OS X 多线程和内存管理>,以及其他一些杂七杂八的书籍或者博客. GCD已经面世很久了,基于GCD面向对象

iOS开发:深入理解GCD 第二篇(dispatch_group、dispatch_barrier、基于线程安全的多读单写)

Dispatch Group在追加到Dispatch Queue中的多个任务处理完毕之后想执行结束处理,这种需求会经常出现.如果只是使用一个Serial Dispatch Queue(串行队列)时,只要将想执行的处理全部追加到该串行队列中并在最后追加结束处理即可,但是在使用Concurrent Queue 时,可能会同时使用多个Dispatch Queue时,源代码就会变得很复杂. 在这种情况下,就可以使用Dispatch Group. 1 2 3 4 5 6 7 8 9 10 11 12 13

ios测试框架的理解

关于ios的测试 Cedar .Specta .Kiwi  .  XCTest Specta和Kiwi的区别就是Kiwi包含了Specta和OCmock以及Expeata所有的功能 测试框架的作用: 由于行业中的干进度,所以我们一般都是不用TDD来测试,而是用BDD来测试. BDD是用来测试的"数据存取"的重要环节. "术语" 理解: BDD(Behavior Driven Development),也就是行为驱动开发,它旨在解决具体问题,帮助开发人员确定应该测试些

iOS runtime的简单理解

最近闲了下来,有时间了就研究一下runtime的运行机制,之前做开发的时候一直也没有特别关注这个东西,只是知道有,但是很少去刻意的使用,研究的不是很深,简单说一下吧,有错误的地方欢迎大家随时指正. Objective-C Runtime 是什么? Objective-C 的 Runtime 是一个运行时库(Runtime Library),它是一个主要使用 C 和汇编写的库,为 C 添加了面相对象的能力并创造了 Objective-C.这就是说它在类信息(Class information) 中

iOS 中delegate的理解与使用(传值)

之前做了半年的iOS,刚入了门,又被拉去转战java,现在iOS的那位大佬离职了,又被弄过来维护app,之前对于iOS中的delegate一直都是半知半解,所以刚好趁着这个机会把我所了解的记下来,以便日后查阅. - delegate的理解 delegate, 也就是代理模式(设计模式的一种),我现在所了解的代理模式是,当我有事要做但是没空的时候,我就可以请别人帮下忙,我告诉你我要做什么,但是具体怎么做,那是你的事了,就比如说,我想去约个妹纸出来玩,但是自己刚好现在有事不能约,或者自己不好意思约,

对于iOS前端框架的理解

iOS前端的架构设计,我所理解的意思就是,使用什么样的模式或者结构敲代码就是各个类怎么协同工作的.或者文件存放的结构.各个类到底如何分工的. 国外有好多关于iOS端的架构的文章,无奈实在英语水平有限,只看了几篇被翻译过的文章.MVC.MVVM.VIPER等还有几个记不住名字的,但是无论什么架构感觉理解的都不是很深刻,具体写代码的时候也没有分的太清楚,也是怎么方便怎么来.最后导致了来回几次的重构,但是重构完成后,过一段时间再看代码的时候还是感觉结构不够清晰,各个类之间的关系比较混乱.现在的项目也是

iOS开发CABasicAnimation动画理解

1.CALayer简介 CALayer是个与UIView很类似的概念,同样有backgroundColor.frame等相似的属性,我们可以将UIView看做一种特殊的CALayer.但实际上UIView是对CALayer封装,在CALayer的基础上再添加交互功能.UIView的显示必须依赖于CALayer.我们同样可以跟新建view一样新建一个layer,然后添加到某个已有的layer上,同样可以对layer调整大小.位置.透明度等.一般来说,layer可以有两种用途:一是对view相关属性