(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. tortoiseGit did not exit cleanly (exit code 128)

    安装并配置好tortoiseGit之后,clone项目时,报错: git did not exit cleanly (exit code 128)如下图: 该问题解决方式: 1.确保Pageant启动 ...

  2. 高级java面试宝典

    1.spring事物的配置 spring事物分为俩种,一种是注解事物,一种是AOP事物注解事物的配置: 事物的隔离级别,事物的传播性,事物的超时回滚,哪些异常回滚,哪些不回滚,有默认的回滚规则注解事物 ...

  3. 一百三十二:CMS系统之前端动态获取后台添加的轮播图

    先准备几张轮播图 排序顺序改为根据优先级倒序排 前端首页接口 @bp.route('/')def index(): banners = BannerModel.query.order_by(Banne ...

  4. python3 __mian和__name__的区别

    1.新建 test.py 模块: def GetModuleName(): print('__name__ = ', __name__) def PrintName(): print('PrintNa ...

  5. Reveal v4(8796) 使用

    文件下载地址   http://xclient.info/s/reveal.html dmg安装成功后, pod install  植入项目. pod 'Reveal-SDK', '~> 4', ...

  6. mysql自身报错、java、reids连接mysql数据库报错汇总

    1.Can't connect to local MySQL server through socket 'tmpmysql.sock' (2) 原因是mysql根本没有启动 2.Access den ...

  7. Spring Boot自定义Mapper的SQL语句

    代码如下: 先创建一个Provider类: public class RptEbankFsymtTranflowingProvider { public String select(String or ...

  8. java面试考点-HashTable/HashMap/ConcurrentHashMap

    HashTable 内部数据结构是数组+链表,键值对不允许为null,线程安全,但是锁是整表锁,性能较差/效率低 HashMap 结构同HashTable,键值对允许为null,线程不安全, 默认初始 ...

  9. 《Java语言程序设计》继承与多态

    一.动手实验:继承条件下的构造方法 调用运行 TestInherits.java 示例,观察输出,注意总结父类与子类之间构造方法的调用关系修改Parent构造方法的代码,显式调用GrandParent ...

  10. sqlmap(网站数据库注入)

    *教程 http://www.nxadmin.com/tools/1241.html 一.ASP网站 1. sqlmap -u “http://www.czypjx.com/News_show.asp ...