NSInvocation简单总结
(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
最新文章
- 将.war文件解压到指定目录
- sdk的目录结构及其功能
- 【bzoj1018】 SHOI2008—堵塞的交通traffic
- IOS开发UI基础之Plis文件-字典转模型
- java 分析方法调用过程
- Java 异常处理机制和集合框架
- Discuz!NT静态文件缓存(SQUID)
- 不同版本PHP之间cURL的区别(-经验之谈)
- Android TXT文件读写
- tq2440+fedora安装qt4.5
- table居中方法之一:设置width,然后为style设置margin:auto
- iOS 多语言 浅析
- 介绍下Python的两个标准库 os 和 sys
- vue传参二
- LVS DR模式搭建、keepalived+lvs
- TextView展示富文本时emoj或图片和文字不对齐的解决方案
- 【Java并发编程】11、volatile的使用及其原理
- “编程利器”:VSCode
- node start - hello world http server
- 设置input标签的placeholder的样式
热门文章
- 004-log-common-logging,Apache整合日志框架JCL门面框架、JCL+log4j
- 5G 与 MEC 边缘计算
- sqlmap注入工具----一次简单的注入(实战)
- linux rz sz替代方案
- 【leetcode_easy】541. Reverse String II
- django 之(三) --- 认证|权限
- vscode插件Project Manager
- bootstrap table checkbox获得选中得数据
- RestTemplate实践(及遇到的问题)
- 关于keepalived执行后日志狂刷IPVS: Can't initialize ipvs: Protocol not available的问题