1.前沿
接上一遍,方法的慢速与快速方法查找流程,都没有找到方法,这时候将会进入方法动态决议流程。源码如:
if (slowpath(behavior & LOOKUP_RESOLVER)) {
//^= 逻辑异或
behavior ^= LOOKUP_RESOLVER;
return resolveMethod_locked(inst, sel, cls, behavior);
}
以上方法为何会执行多次呢?,带着这个问题探索如下:
2.探索动态决议resolveMethod_locked
方法
下层源码:
1.判断对象的类是否存在,存在调用
resolveInstanceMethod
,并且在这个方法中进行容错处理。之后在查询方法。源码如图
因此,系统会在这之后发送一次消息
,也让动态方法决议的作用,在给一次查询的机会。
2.类方法动态决议,执行resolveInstanceMethod
else条件。步骤同对象方法一样。
假如为了不让找不到的方法,造成程序不崩溃,可以用如下方法解决:
步骤1:
在类方法的动态决议中为什么也需要拯救一次呢?
因为类方法在元类中是以对象方法的形式存在的。重点类的
继承链图
步骤2:新建一个NSObject+(LQ)
分类文件
并且实现如图的方法: // 调用方法的时候 - 分类
+ (BOOL)resolveInstanceMethod:(SEL)sel{
NSLog(@"%@ 来了",NSStringFromSelector(sel));
if (sel == @selector(say666)) {
NSLog(@"%@ 来了",NSStringFromSelector(sel));
IMP imp = class_getMethodImplementation(self, @selector(sayMaster));
Method sayMMethod = class_getInstanceMethod(self, @selector(sayMaster));
const char *type = method_getTypeEncoding(sayMMethod);
return class_addMethod(self, sel, imp, type);
}
else if (sel == @selector(sayNB)) {
IMP imp = class_getMethodImplementation(objc_getMetaClass("LGPerson"), @selector(lgClassMethod));
Method sayMMethod = class_getInstanceMethod(objc_getMetaClass("LGPerson"), @selector(lgClassMethod));
const char *type = method_getTypeEncoding(sayMMethod);
return class_addMethod(objc_getMetaClass("LGPerson"), sel, imp, type);
}
return NO;
}
注意,此方法不是最好的解决问题的方法
3、本文重点消息转发探索
当动态决议完成后,系统做了啥?
结束后,系统:进入此log_and_fill_cache
方法中。重点是查看logMessageSend
在logMessageSend方法中能生成信息文件->
command+shift+g
//输入/tmp/msgSends/
,运行工程
结果如下
。
验证步骤:
1)步骤1.在相应的类中实现
//快速转发流程
- (id)forwardingTargetForSelector:(SEL)aSelector{
NSLog(@"快速转发:%s == %@",__func__, NSStringFromSelector(aSelector));
// return [super forwardingTargetForSelector:aSelector];
//找个存在的方法做事情
// return [LGStudent alloc];
//runtime +aSelector + addMethod + imp,只需要返回对象
// return self;
return [super forwardingTargetForSelector:aSelector];
}
结果如图:
如何补救呢?
步骤1:
定义好补救的类,如图方式,方可补救
结论:当动态决议之后,通过消息快速转发,
若是找到补救方法,则消息处理
,程序棒棒的。
如是没找到,或者返回nil
,进入下一步步骤2
2.)步骤2:
慢速转发。
实现methodSignatureForSelector
,返回消息的签名NSMethodSignature
搭配一个方法的使用- (void)forwardInvocation:(NSInvocation *)anInvocation
完整的如下:
,总结
,通过以上步骤的探索,消息转发流程如下: