IOS NSInvocation应用与理解

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

一、初始化与调用

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

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

- (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");

}

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

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

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

- (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占用。下面这样写也没有任何问题:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

- (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对象,是可以有返回值的,然而这个返回值,并不是其所调用函数的返回值,需要我们手动设置:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

- (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-09-07 06:06:16

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

iOS开发之深入理解GCD

本文翻译自 http://www.raywenderlich.com/60749/grand-central-dispatch-in-depth-part-1 原作者:Derek Selander 译者:@nixzhu Github: https://github.com/nixzhu/dev-blog   虽然 GCD 已经出现过一段时间了,但不是每个人都明了其主要内容.这是可以理解的:并发一直很棘手,而 GCD 是基于 C 的 API ,它们就像一组尖锐的棱角戳进 Objective-C 的

iOS 块的简单理解

占位 自动转载器那小子,你转完了没? 转完了,我开写了哈! Block,就两个事儿,一个是引用,一个是实例,除了实现处,其它地方都是引用. 以此思路,再继续看看引用和实现的定义方式吧. 参考官方文档. 后补 ========== 最近在忙一件大事,好事有结果了,而确没有明确结果. 今天又用到 block 构建复用架构,发现短短的一两周时间,就有点忘记 block 的用法了. 看来真得整理一下了. ========== 引用 和 实现 引用即名称,返回类型是要有的 实现可以没有,它的内部返回值就是

深入理解iOS的状态栏_IOS

一.状态栏的隐藏 状态栏的隐藏主要有两种方法,下面来一起看看吧. 方法一:通过代码控制 @interface UIApplication(UIApplicationDeprecated) // Setting statusBarHidden does nothing if your application is using the default UIViewController-based status bar system. @property(readwrite, nonatomic,ge

理解iOS的内存管理

远古时代的故事 那些经历过手工管理内存(MRC)时代的人们,一定对 iOS 开发中的内存管理记忆犹新.那个时候大约是 2010 年,国内 iOS 开发刚刚兴起,tinyfool 大叔的大名已经如雷贯耳,而我还是一个默默无闻的刚毕业的小子.那个时候的 iOS 开发过程是这样的: 我们先写好一段 iOS 的代码,然后屏住呼吸,开始运行它,不出所料,它崩溃了.在 MRC 时代,即使是最牛逼的 iOS 开发者,也不能保证一次性就写出完美的内存管理代码.于是,我们开始一步一步调试,试着打印出每个怀疑对象的

IOS开发网站汇总

十分钟让你明白Objective-C的语法(和Java.C++的对比) http://blog.csdn.net/totogo2010/article/details/7632384 iOS学习之sqlite的创建数据库,表,插入查看数据 http://blog.csdn.net/totogo2010/article/details/7702207 iOS SQLite3初试用 http://mobile.51cto.com/iphone-321932.htm ios简单使用sqlite3 ht

《iPhone与iPad开发实战—iOS经典应用剖析》连载八

3.3.5 主视图控制器代码 主视图控制器是MainViewController,由于视图使用的控件都已经在视图MainView中定义了,所以在视图控制器MainViewController代码很少了,在本应用中还设计了按钮按下和按钮选择时候的普通和高亮状态效果.这些效果可以在检查器中设定,也可以通过代码设定,本应用是通过代码设定这些效果.先看看主视图控制器类MainViewController,它的h文件定义请参考"代码清单3-5Password/Classes/MainViewControl

iOS 混合应用的关键点分析 - 仿 Android 平台 WebView 可注入本地对象方法的功能实现要点

iOS 混合应用的关键点分析 - 仿 Android 平台 WebView 可注入本地对象方法的功能实现要点 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. 对于 iOS 和 Android 平

iOS创建与使用静态库_IOS

在日常项目开发中,不论是为了两个公司项目上的业务交流还是为了减少项目的编译时间,有的时候我们会把项目中的私密内容打包成静态库,或者是把项目中变动较少一部分打包成静态库以便提高编译效率,那么下面我们就来学习一下"iOS-静态库的创建与使用": (一)iOS静态库.动态库与Framework静态库与动态库的区别 (1)什么是库? 库(Library)直白一点说就是一段编译好的二进制代码,加上头文件就可以供别人使用;(例如: iOS中Objective-C编译下的.h和.m文件,打包静态库后

聊天记录导出

问题描述 朋友们,请问1.如果同时有两个聊天窗口在进行对话,那(服务器端)根据时间戳导出消息记录的是不是混在一起的呢?我们只需要一次会话的消息数据2.导出到服务器后,那数据类型我可以在移动端直接转成EMMessage么(iOS)? 解决方案 你理解可能有点问题,根据时间戳导出聊天记录是导的app下所有的聊天记录,每条消息都会有from 跟to 标识,怎么会混在一起你.至于你需要某个会话的聊天数据,当你把所有的聊天记录导到自己服务器上之后,就可以随便操作了.导到自己服务器的聊天记录,你就可以做进一