(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

最新文章

  1. 将.war文件解压到指定目录
  2. sdk的目录结构及其功能
  3. 【bzoj1018】 SHOI2008—堵塞的交通traffic
  4. IOS开发UI基础之Plis文件-字典转模型
  5. java 分析方法调用过程
  6. Java 异常处理机制和集合框架
  7. Discuz!NT静态文件缓存(SQUID)
  8. 不同版本PHP之间cURL的区别(-经验之谈)
  9. Android TXT文件读写
  10. tq2440+fedora安装qt4.5
  11. table居中方法之一:设置width,然后为style设置margin:auto
  12. iOS 多语言 浅析
  13. 介绍下Python的两个标准库 os 和 sys
  14. vue传参二
  15. LVS DR模式搭建、keepalived+lvs
  16. TextView展示富文本时emoj或图片和文字不对齐的解决方案
  17. 【Java并发编程】11、volatile的使用及其原理
  18. “编程利器”:VSCode
  19. node start - hello world http server
  20. 设置input标签的placeholder的样式

热门文章

  1. 004-log-common-logging,Apache整合日志框架JCL门面框架、JCL+log4j
  2. 5G 与 MEC 边缘计算
  3. sqlmap注入工具----一次简单的注入(实战)
  4. linux rz sz替代方案
  5. 【leetcode_easy】541. Reverse String II
  6. django 之(三) --- 认证|权限
  7. vscode插件Project Manager
  8. bootstrap table checkbox获得选中得数据
  9. RestTemplate实践(及遇到的问题)
  10. 关于keepalived执行后日志狂刷IPVS: Can't initialize ipvs: Protocol not available的问题