- 调用方法的流程:
- 1、从cache缓存查找
- 2、缓存没有,则从对象方法列表或者父类的方法列表去查找
- 3、方法列表没找到,则进行消息解析
imp = forwardImp
for(){
if (slowpath((curClass = curClass->getSuperclass()) == nil)) {
// No implementation found, and method resolver didn't help.
// Use forwarding.
imp = forward_imp;
break; //跳出循环
}
}
//进入方法解析
// No implementation found. Try method resolver once.
if (slowpath(behavior & LOOKUP_RESOLVER)) {
behavior ^= LOOKUP_RESOLVER;
return resolveMethod_locked(inst, sel, cls, behavior);
}
进入方法的解析 resolveMethod_locked
-
resolveInstanceMethod
-
resolveClassMethod,
-
如果没有进行方法重新解析则会报错,没找到方法
方法名SEL没有找到IMP则会报错
实例方法没实现,调用 resolveInstanceMethod
- 则添加实例方法的实现
- 运行时,动态给对象添加方法
- 添加的方法会缓存的对象的方法列表中
类方法没实现,调用resolveClassMethod
- 添加类方法
- 如果没找到方法实现,则会再次调用resolveInstanceMethod
- 查看有没有实例方法实现
- 类方法最终也会缓存到对象的方法列表
- 注意: class_getMethodImplementation(类对象, 方法);
- 1、类对象 对应的是实例方法,没有实例方法(方法找不到)会死循环
- 2、类对象 如果对应的是类方法(应该是实例方法)找不到也会死循环
+(BOOL)resolveInstanceMethod:(SEL)sel { NSLog(@"%s",func); IMP imp = class_getMethodImplementation(self.class, @selector(addInstanceMethod3));
class_addMethod(self.class, sel, imp, "v@:"); return [super resolveInstanceMethod:sel]; }
- 注意:IMP imp = class_getMethodImplementation(类对象, 实例方法));
- IMP imp = class_getMethodImplementation(元类, 类方法));
- 1、类对象对应的实例方法没实现,则进入 resolveInstanceMethod
- 2、如果是元类 和实例方法也是方法找不到死循环 +(BOOL)resolveClassMethod:(SEL)sel { NSLog(@"%s",func);
IMP imp = class_getMethodImplementation(self.class, @selector(addClassMethod));
class_addMethod(objc_getMetaClass("Person"), sel, imp, "v@:");
return [super resolveClassMethod:sel]; }
如果找到方法则缓存方法,返回方法实现
- 方法缓存到当前对象的方法列表里
消息决议没有动态添加方法实现,接下来消息转发
消息快速转发
- -(id)forwardingTargetForSelector:(SEL)aSelector {
- 返回能响应消息的对象
- }
- 快速转发没处理,还会进入慢速转发
慢速转发
- 1、-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{}
- 2、-(void)forwardInvocation:(NSInvocation *)anInvocation{}
- 两个方法配合实现消息慢速转发
- 给消息添加一个响应的选择器来响应消息指行 invokeWithTarget:
-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
NSLog(@"%s-%@",func,NSStringFromSelector(aSelector));
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}
-(void)forwardInvocation:(NSInvocation *)anInvocation {
Teacher *t = [Teacher alloc];
if ([self respondsToSelector:anInvocation.selector]) {
[anInvocation invokeWithTarget:self];
}else if ([t respondsToSelector:anInvocation.selector] ) {
[anInvocation invokeWithTarget:t];
}else {
NSLog(@"%s-%@",func,NSStringFromSelector(anInvocation.selector)); } }
查找消息查找流程的代码
其中消息转发的日志文件中显示了消息的快速转发和慢速转发
至此,如果还没有相应方法则提示方法未实现或者报错没找到方法
消息传递的过程中的三次机会分别是
- 1、消息决议,动态添加方法
- 2、快速转发,找到响应方法的对象,执行消息
- 3、慢速转发:找到能够响应方法的选择器,执行消息