本文由快学吧个人写作,以任何方式转载请标明原文出处
一、预备资料
objc4-818.2
对应mac的版别是11.1。可根据自己的系统版别挑选能够进行调试的源码。
二、思路
- 无论是上一章还是本章,都是对十三章
lookUpImpOrForward
的一个完善。 - 动态办法抉择之后,
lookUpImpOrForward
还有一个流程是 :日志和增加缓存。 - 那么关于办法查找的日志中都会有一些什么?
三、项目预备
-
为了日志中没有其他因素的搅扰,所以创立一个新的mac项目。
-
创立一个新的mac项目,并在其中创立一个JDMan类和一个JDKid类,都继承于NSObject。
-
然后在JDMan.h中增加一个实例办法,而且不完成这个实例办法。然后在main.m中实例化一个JDMan的实例,并让实例调用这个实例办法。如下图 :
四、怎么找到lookUpImpOrForward
的日志
- 在818.2的源码中,找到
lookUpImpOrForward
的源码。找到done:
中的日志和缓存增加的源码。
- 进入
log_and_fill_cache
源码,如下 :
- 发现一个宏判别和一个判别条件。
(1). 宏判别的条件SUPPORT_MESSAGE_LOGGING
在!TARGET_OS_OSX
的条件下为0,由于我创立的是mac项目,所以!TARGET_OS_OSX
== 0。则SUPPORT_MESSAGE_LOGGING
== 1。所以会进入if
判别。
(2). objcMsgLogEnabled
在源码中找到默认是false。
-
if
判别中的logMessageSend
源码 :
-
找到了日志存储的途径。先直接运转上面预备的项目,然后用Finder进入这个途径,检查/tmp目录下是否有
msgSends
前缀的日志文件。成果会发现没有。也就是说,objcMsgLogEnabled
在默认为false的情况下,是不会生成日志的,那么假如让objcMsgLogEnabled
为true,是否会生成日志? -
怎么让
objcMsgLogEnabled
为true。肯定不能直接在源码中修改。所以查找objcMsgLogEnabled
,发现如下函数能够为它赋值 :
- 在上面创立的项目中,在main.m中,为
instrumentObjcMessageSends
函数做一个外部声明进行扩充,让我们能够调用它。并将main.m代码改成如下 :
- 运转项目,项目会溃散,由于未完成
ceShi
办法,这个无所谓。然后进入/tmp
途径下,找到日志文件,翻开日志 :
- 会发现在
resolveInstanceMethod
动态办法抉择之后,办法的查找流程还会调用两个函数 :
forwardingTargetForSelector
和methodSignatureForSelector
。这个就是所谓的音讯转发。
五、forwardingTargetForSelector:
- 详细信息能够找xcode供给的官方
Help
文档(command + shift + 0(零)),查找forwardingTargetForSelector
。这儿不做详细展现。
(1). 回来值id : 想要哪个目标处理未完成的办法,就回来哪个目标。
(2). 参数aSelector : 未完成的办法的SEL。
- 在818.2源码中查找
forwardingTargetForSelector
,发现是有两个办法的,一个类办法,一个实例办法 :
- 举例 :
(1). 运用上面创立的项目。再给JDMan增加一个类办法,而且同样不在JDMan中进行完成。
(2). 在JDMan.m中完成forwardingTargetForSelector
的类办法和实例办法。
(3). 既然转发给了JDKid,那么在JDKid.m中完成(1)图中的两个JDMan的办法。
(4). 运转代码 :
(5). 实例办法就用实例办法的forwardingTargetForSelector
进行转发。
类办法则就用类办法的forwardingTargetForSelector
进行转发。类办法不要用实例办法的,实例办法也不要用类办法的forwardingTargetForSelector
。
六、methodSignatureForSelector:
- 详细信息能够找xcode供给的官方
Help
文档(command + shift + 0(零)),查找methodSignatureForSelector
。这儿不做详细展现。
(1). 回来值NSMethodSignature
: 办法的encodingType,也就是办法的编码类型,包含办法的回来值和参数的类型信息。
(2). 参数aSelector : 未完成的办法的SEL。
-
NSMethodSignature
的初始化办法也能够在Help
文档中找到 :
-
methodSignatureForSelector
需求调配forwardInvocation
办法一同运用。 -
举例 :
(1). 运用上面举例中的项目,不完成forwardingTargetForSelector
。JDMan.m中代码 :
(2). 运转成果
(3). 实例就用实例的办法,类就用类办法的。
- 能够只完成
methodSignatureForSelector
,不完成forwardInvocation
中的代码,就是forwardInvocation
要写出来,可是内部不写任何东西,也不会溃散。
七、总结
音讯转发有两种办法 :
-
forwardingTargetForSelector
,有实例办法和类办法,能够回来一个对未完成办法进行完成的目标或者类,这个目标或者类内部假如完成了这个未完成的办法,则不会报错。 -
methodSignatureForSelector
,有实例办法和类办法,会回来一个NSMethodSignature
目标。相当于把未完成办法的encodingType(办法类型编码)存放到进程的调度中心里。等待着其他完成者来完成。 -
methodSignatureForSelector
和forwardInvocation
调配运用。能够不在forwardInvocation
内写代码。可是必须要写出来forwardInvocation
这个办法。