(1)用法

NSInvocation是调用函数的另一种方式,它将调用者,函数名,参数封装到一个对象,然后通过一个invoke函数来执行被调用的函数,其思想就是命令者模式,将请求封装成对象。

例如,有这样一个类:

@implementation CA

-(int)AddA:(int)a andB:(int)b

{

return a + b;

}

@end

一般调用函数的方式是:

CA *ca = [CA new];

int result = [ca AddA:2 andB:3];

或者用performSelector,但是后者只能有一个参数,所以对于有多个参数的情况,就可以用NSInvocation来调用。

示例代码:

    CA *ca = [CA new];

    NSMethodSignature *sig= [[CA class] instanceMethodSignatureForSelector:@selector(AddA:andB:)]; //根据selector得到一个签名对象

    NSInvocation *invocation=[NSInvocation invocationWithMethodSignature:sig];//根据该签名对象创建一个NSInvocation对象

    invocation.target = ca;//指定调用函数的对象

    invocation.selector = @selector(AddA:andB:);//指定要调用的函数名

    int a = 20;

    int b = 30;

    [invocation setArgument:&a atIndex:2];//指定参数,以指针方式,并且第一个参数的起始index是2,因为index为1,2的分别是self和selector

    [invocation setArgument:&b atIndex:3];

    [invocation retainArguments];//因为NSInvocation不会自己去retain参数,因此需要用户去retain,当然本例中其实没必要

      [invocation invoke];

    //获取返回值的过程略有点复杂,需要根据起类型长度分配空间,然后转为对象

    //如果是int,BOOL等简单类型,返回的对象是NSNumber

    //如果是其他类型的对象,返回的对象是NSValue

     //判断返回值类型,用strcmp(returnType, @encode(NSInteger))

    const char *returnType = sig.methodReturnType;

    id returnValue;

    NSUInteger length = [sig methodReturnLength];

    void *buffer = (void *)malloc(length);

    [invocation getReturnValue:buffer];

    returnValue = [NSNumber numberWithInteger:*((NSInteger*)buffer)];//int的情况

    //returnValue = [NSNumber numberWithBool:*((BOOL*)buffer)]; //bool 的情况

      //returnValue = [NSValue valueWithBytes:buffer objCType:returnType];// 其他类型的情况

    int result = [returnValue intValue];

    NSLog(@"result=%d",result);

  

(2) 用到NSInvocation的一些场合

[NSTimer scheduledTimerWithTimeInterval:0.1 invocation:invocation repeats:YES]

NSInvocationOperation //它是NSOperation的派生类,用NSInvoation来初始化

(void)forwardInvocation:(NSInvocation *)anInvocation

这个函数与forwardTargetWithSelector类似,当某个对象收到一个selector消息,但该对象没有实现该selector,且实现forwardInvocation,那么系统会构造一个NSInvocation对象,并调用forwardInvocation,这样在函数里面,用户就可以用[invocation invokeWithTarget:friend];来让另一个对象来执行这个selector.

要实现这个函数,还必须实现methodSignatureForSelector,因为这个anInvocation是系统构造的,构造这个对象需要有签名对象,这个对象必须由用户提供。所以这个函数用起来比forwardingTargetForSelector麻烦

另外,由于使用forwardInvocation可以使得一个对象将它没有实现的方法转发给其他对象,因此可以变相的实现多继承。

参考链接:http://www.cnblogs.com/pengyingh/articles/2359199.html

NSInvocation简单总结的更多相关文章

  1. Objective-C中NSInvocation的使用

    OC中调用方法某个对象的消息呦两种方式: #1. performanceSelector: withObject: #2. NSInvocation. 第一个PerformaceSelector比较常 ...

  2. IOS NSInvocation用法简介

    IOS NSInvocation用法简介 2012-10-25 19:59 来源:博客园 作者:csj007523 字号:T|T [摘要]在 iOS中可以直接调用某个对象的消息方式有两种,其中一种就是 ...

  3. NSInvocation的使用(转)

    转载自:http://www.cnblogs.com/pengyingh/articles/2359199.html http://blog.iosxcode4.com/?p=125 在 iOS中可以 ...

  4. ios NSMethodSignature and NSInvocation 消息转发

    1.首先获取消息转发时连个函数内部具体内容 MARK:这里是拿[@"xxxxx" length]调用拿来举例说明 (lldb) po signature <NSMethodS ...

  5. 关于 NSInvocation

    Invocation   调用的意思. 可想而知NSInvocation 是一个 方法调用 封装的类. 这体现了  面向对象的思想, 及一切皆对象.函数也不例外. 一般编程中,应该很少用到这个. 但是 ...

  6. 【造轮子】打造一个简单的万能Excel读写工具

    大家工作或者平时是不是经常遇到要读写一些简单格式的Excel? shit!~很蛋疼,因为之前吹牛,就搞了个这东西,还算是挺实用,和大家分享下. 厌烦了每次搞简单类型的Excel读写?不怕~来,喜欢流式 ...

  7. Fabio 安装和简单使用

    Fabio(Go 语言):https://github.com/eBay/fabio Fabio 是一个快速.现代.zero-conf 负载均衡 HTTP(S) 路由器,用于部署 Consul 管理的 ...

  8. node.js学习(三)简单的node程序&&模块简单使用&&commonJS规范&&深入理解模块原理

    一.一个简单的node程序 1.新建一个txt文件 2.修改后缀 修改之后会弹出这个,点击"是" 3.运行test.js 源文件 使用node.js运行之后的. 如果该路径下没有该 ...

  9. 哪种缓存效果高?开源一个简单的缓存组件j2cache

    背景 现在的web系统已经越来越多的应用缓存技术,而且缓存技术确实是能实足的增强系统性能的.我在项目中也开始接触一些缓存的需求. 开始简单的就用jvm(java托管内存)来做缓存,这样对于单个应用服务 ...

随机推荐

  1. java定时任务Timer/scheduleAtFixedRate

    Timer类是用来执行任务的类,定时器 scheduleAtFixedRate模式可以用,在这个模式下,Timer会尽量的让任务在一个固定的频率下运行. 参考:http://swiftlet.net/ ...

  2. 假如React没了JSX

    如题,想必React大家早已不陌生,而React里面的JSX都是玩的得心应手了,但是假如说React里面没有了React那会是一种什么样的情形呢,我们来简单的看一下. 首先我们来实现一个简单的list ...

  3. JAVA 基础编程练习题17 【程序 17 猴子吃桃问题】

    17 [程序 17 猴子吃桃问题] 题目:猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个 第二天早上又 将剩下的桃子吃掉一半,又多吃了一个.以后每天早上都吃了前一天剩下的一 ...

  4. array_splice 在数组某位置插入数据

    $arr=array('a','b','c','d','e','f','g');//目标数组 $i_arr=array(');//要插入的数组 $n=;//插入的位置 array_splice($ar ...

  5. [System.Serializable],

    [System.Serializable]添加在类,枚举,结构前面,可以让该这些对象在inspector中显示 [SerializeField]是设置非public 成员对象在inspector中显示

  6. [BAT] SetX 永久设置环境变量

    SetX 有三种使用方式: 语法 1: SETX [/S system [/U [domain\]user [/P [password]]]] var value [/M] 语法 2: SETX [/ ...

  7. 【VS开发】IPicture在指定窗口绘制图

    1.利用IPicture接口加载.显示图片 IPicture接口管理一个图片对象和它的属性.图片对象提供对Bitmap Icon Metafile的语言不相关的抽象支持.图像对象的主要接口是IPict ...

  8. 创建多个Fragment可滑动界面

    创建新项目,选择Tabbed Activity 默认就有2个Fragment,这里我们删除相关代码. 在切换时 FragmentPagerAdapter onDestroyView onCreateV ...

  9. 《你必须知道的495个C语言问题》读书笔记之第1-2章:声明和初始化

    1. C标准中并没有精确定义数值类型的大小,但作了以下约束: (1) char类型可以存放小于等于127的值: (2) short int和int可以存放小于等于32767的值: (3) long i ...

  10. mybatis+mysql insert添加数据后返回数据主键id

    1.根据useGeneratedKeys获取返回值,部分数据库不支持 修改mybatis xml <insert id="insertUser" useGeneratedKe ...