上一篇文章中iOS-底层原理10-动态方法决议&消息转发探索了动态方法决议和消息转发,有两个问题还需要探索
问题一:动态方法决议+ (BOOL)resolveInstanceMethod:(SEL)sel里面,没有对sel方法say666进行重新指定imp,则此动态决议方法+ (BOOL)resolveInstanceMethod:(SEL)sel会走两次,为什么会走两次呢???
- 第一次动态方法决议后,方法返回,是什么时候进入第二次动态方法决议方法的呢???通过打印第二进入前的堆栈情况,获取堆栈信息如下,得到第二次触发是在CoreFoundation`-[NSObject(NSObject) methodSignatureForSelector:],后面探索实质为消息的慢速转发流程。
- 通过hopper反汇编查看消息转发流程:
___forwarding_prep_0___
->____forwarding___
->forwardingTargetForSelector:
->methodSignatureForSelector:
查看methodSignatureForSelector:源码实现,进入___methodDescriptionForSelector
->class_getInstanceMethod
从而在class_getInstanceMethod方法中打断点调试下。
class_getInstanceMethod断点调试,进入到消息的慢速查找流程lookUpImpOrForward(nil, sel, cls, LOOKUP_RESOLVER)
- 第二次动态方法决议还没找到imp,程序报错_objc_msgForward_impcache
问题二:消息的快速转发流程中,在forwardingTargetForSelector:方法中动态添加本类的sayHello的Imp,结果程序崩溃,为什么呢???
新建LGStudent的类,将消息转发给LGStudent的对象,并不会报错,能正常执行
- 转发给LGStudent对象新加的方法程序能正常转发,通过反编译代码,查看反编译的- (id)forwardingTargetForSelector:(SEL)aSelector源码
- return self,则rax == rbx,进入loc_64a67,发现
if (strncmp(r13, "_NSZombie_", 0xa) == 0x0) goto loc_64dc1;
,进入goto loc_64dd7