objc_msgSend
包括以下三個步驟
- 消息發(fā)送
- 動態(tài)方法解析
- 消息轉(zhuǎn)發(fā)
消息發(fā)送
image.png
動態(tài)方法解析
struct objc_method_t{
SEL name;
char *types;
IMP imp;
};
- (void)other{
NSLog(@"%s",__func__);
}
+ (BOOL)resolveInstanceMethod:(SEL)sel{
NSLog(@"被調(diào)用了%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];
}
消息轉(zhuǎn)發(fā)
- (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");
*/
}
總結(jié):
objc_msgSend
實質(zhì)上是像接收者發(fā)送一個selector
消息,開始的時候會在緩存中查找,沒找到則從類或者元類中的方法列表中查找,找到則將其緩存起來并調(diào)用,如果從類對象or元類對象中沒找到則會去其父類中查找,如果到基類都沒找到則進入動態(tài)方法解析resolveInstanceMethod
如果這步不做處理,則會進如消息轉(zhuǎn)發(fā)階段,forwardingTargetForSelector
如果這步也不處理則會進入下一階段methodSignatureForSelector
和methodSignatureForSelector
,如果這里也不進行處理,則會拋出異常unrecognized selector sent to instance
.
image.png