NSInvocation是命令模式的一种实现,它包含选择器、方法签名、相应的参数以及目标对象。所谓的方法签名,即方法所对应的返回值类型和参数类型。当NSInvocatio被调用,它会在运行时通过目标对象去寻找对应的方法,从而确保唯一性,可以用[receiver message]来解释。实际开发过程中直接创建NSInvocation的情况不多见,这些事情通常交给系统来做。比如bang的JSPatch中arm64方法替换的实现就是利用runtime消息转发最后一步中的NSInvocation实现的。
正文
基于这种命令模式,可以利用NSInvocation调用任意SEL甚至block。NSInvocation与NSMethodSignature配合来完成调用。NSMethodSignature这个类的对象保存了方法的名称、参数和返回值
- SEL
系统NSObject
自带的performSelector
默认只支持一个参数,我们可以给NSObject增加一个category,增加以下方法就可以支持多个参数的调用了
|
|
block
|
|
SEL与block比较
- invocation
SEL既有target也有selector,block只有target- signature
SEL有两个隐藏参数,类型均为@,分别对应target和selector。block有一个隐藏参数,类型为@?,对应target且block的target为他本身- type
以OC对象为例:SEL的type为@,block的type会跟上具体类型,如@”NSString”
再谈block
在block的invocation中有这样的代码
_Block_signature其实是JavaScriptCore/ObjcRuntimeExtras.h
中的私有API(这个头文件并没有公开可以戳这里查看)
既然苹果把API封了,那就自己实现咯,万能的github早有答案CTObjectiveCRuntimeAdditions把CTBlockDescription.h
和CTBlockDescription.m
拖到项目中,代码这样写
NSInvocation.h
|
|