博客> NSInvocation, object的消息转发机制
NSInvocation, object的消息转发机制
2019-07-16 19:18 评论:0 阅读:328 lvhahaha
ios runtime NSInvocation

NSInvocation的定义

NSInvocation是一个消息调用类,它包含了所有OC消息的成分:target、selector、参数以及返回值。NSInvocation可以将消息转换成一个对象,消息的每一个参数能够直接设定,而且当一个NSInvocation对象调度时返回值是可以自己设定的。一个NSInvocation对象能够重复的调度不同的目标(target),而且它的selector也能够设置为另外一个方法签名。NSInvocation遵守NSCoding协议,但是仅支持NSPortCoder编码,不支持归档型操作。 比如bang的JSPatch中arm64方法替换的实现就是利用runtime消息转发最后一步中的NSInvocation实现的。

1、一般的使用

消息转发的两个方法 一种是performSelector:withObject; 再一种就是NSInvocation。 第一种方式比较简单,能完成简单的调用。但是对于>2个的参数或者有返回值的处理,那performSelector:withObject就显得有点有心无力了,那么在这种情况下,我们就可以使用NSInvocation来进行这些相对复杂的操作

A.方法签名类:获得一个方法的签名 SEL selector = NSSelectorFromString(@"getSumWithNum1:num2:userName:");

NSMethodSignature *signature = [ViewController instanceMethodSignatureForSelector:selector];

B.根据方法签名来创建NSInvocation对象。 NSInvocation中保存了方法所属的对象/方法名称/参数/返回值,其实NSInvocation就是将一个方法变成一个对象。

C、创建NSInvocation对象 NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; //设置方法调用者 invocation.target = self; //注意:这里的方法名一定要与方法签名类中的方法一致 invocation.selector = selector;

NSNumber *num1 = @(1);
NSNumber *num2 = @(2);
NSString *userName = @"小明";
[invocation setArgument:&num1 atIndex:2];
[invocation setArgument:&num2 atIndex:3];
[invocation setArgument:&userName atIndex:4];

//这里的Index要从2开始,以为0跟1已经被占据了,分别是self(target),selector(_cmd)

D、调用invoke方法 [invocation invoke];

E、实现run:方法

  • (void)getSumWithNum1:(NSNumber )num1 num2:(NSNumber )num2 userName:(NSString *)userName { NSLog(@"num1 = %@, num2 = %@, userName = %@", num1, num2, userName); } 打印结果如下:  屏幕快照 2019-02-26 上午11.29.00.png

如果使用了带返回值的这样处理。 可以在invoke方法前添加,也可以在invoke方法后添加??? -- 错误,只能在invoke 后添加

 if (signature.methodReturnLength > 0) {
       int result;

       [invocation getReturnValue:&result];

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

 屏幕快照 2019-02-26 上午11.35.12.png

下篇介绍NSInvocation 的高级使用。

demo地址

收藏
2
sina weixin mail 回到顶部