Runtime(二)
2019-05-30 本文已影响0人
comsubin
objc_msgSend
包括以下三个步骤
- 消息发送
- 动态方法解析
- 消息转发
消息发送
image.png动态方法解析
struct objc_method_t{
SEL name;
char *types;
IMP imp;
};
- (void)other{
NSLog(@"%s",__func__);
}
+ (BOOL)resolveInstanceMethod:(SEL)sel{
NSLog(@"被调用了%s",__func__);
if (sel == @selector(test)) {
struct objc_method_t *otherMethod = (struct objc_method_t *)class_getInstanceMethod(self, @selector(other));
class_addMethod(self, sel, otherMethod->imp, otherMethod->types);
return YES;
}
return [super resolveInstanceMethod:sel];
}
消息转发
- (id)forwardingTargetForSelector:(SEL)aSelector{
if (aSelector == @selector(test)) {
//objc_msgSend(student,sel);
return [[student alloc]init];
}
return [super forwardingTargetForSelector:aSelector];
}
如果forwardingTargetForSelector
没有处理则进入下面方法
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
if (aSelector == @selector(test)) {
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}
return [super methodSignatureForSelector:aSelector];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation{
/*
NSLog(@"abc");
*/
}
总结:
objc_msgSend
实质上是像接收者发送一个selector
消息,开始的时候会在缓存中查找,没找到则从类或者元类中的方法列表中查找,找到则将其缓存起来并调用,如果从类对象or元类对象中没找到则会去其父类中查找,如果到基类都没找到则进入动态方法解析resolveInstanceMethod
如果这步不做处理,则会进如消息转发阶段,forwardingTargetForSelector
如果这步也不处理则会进入下一阶段methodSignatureForSelector
和methodSignatureForSelector
,如果这里也不进行处理,则会抛出异常unrecognized selector sent to instance
.