OC中的方法调用底层转成了objc_msgSend函数的调用,给receiver方法调用者发送一条@selector消息。
objc_msgSend底层有3大阶段:
1:消息发送
首先根据receiver对象的isa找到类对象,在类对象的方法缓存cache中查找找到就调用,没找到在类对象的class_rw_t的方法数组method_list中遍历查找,找到就调用,并将方法缓存到类对象的cache中。没找到根据super_class指针找到父类的类对象,在父类的方法缓存中查找,找到就调用,并存入receiver类对象的方法缓存中,没找到在父类的方法列表中查找,找到就调用,并存入receiver类对象的方法缓存中,没找到继续根据super_class指针找到父类,在父类中查找。如果一直找到NSObject基类都没有找到要调用的方法,进入动态方法解析。
2:动态方法解析 resolveInstanceMethod
调用resolveInstanceMethod/resolveClassMethod动态添加方法的实现,成功添加方法实现后,该方法会存入class_rw_t的方法列表中。重新进入消息发送。如果消息发送阶段仍然没有找到要调用的方法,已经进行过一次动态方法解析,直接进入消息转发。
+ (BOOL)resolveInstanceMethod:(SEL)sel {
if (sel == @selector(test)) {
Method method = class_getInstanceMethod(self, @selector(testMethod));
class_addMethod(self, sel, method_getImplementation(method), method_getTypeEncoding(method));
return YES;
}
NSLog(@"%s", __func__);
return [super resolveInstanceMethod:sel];
}
- (void)testMethod {
NSLog(@"%s", __func__);
}
3:消息转发forwardingTargetForSelector
调用forwardingTargetForSelector方法,如果转给其他对象处理,会向返回对象发送消息。如果返回nil,没有转给其他对象处理,进入方法签名methodSignatureForSelector。如果返回的方法签名正确,进入forwardInvocaiton。
//类方法的消息转发
+ (id)forwardingTargetForSelector:(SEL)aSelector {
if (aSelector == @selector(classMethod:)) {
NSLog(@"forwardingTargetForSelector");
//return [Doctor class]; //相当于objc_msgSend(Doctor, @selector(classMethod:));
//return [[Doctor alloc] init]; //相当于objc_msgSend([[Doctor alloc] init], @selector(classMethod:));
return nil;
}
return [super forwardingTargetForSelector:aSelector];
}
+ (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
if (aSelector == @selector(classMethod:)) {
NSLog(@"methodSignatureForSelector");
return [NSMethodSignature signatureWithObjCTypes:"i@:i"];
}
return [super methodSignatureForSelector:aSelector];
}
+ (void)forwardInvocation:(NSInvocation *)anInvocation {
NSLog(@"forwardInvocation");
int age;
[anInvocation getArgument:&age atIndex:2];
int ret;
[anInvocation getReturnValue:&ret];
NSLog(@"age = %d, ret = %d", age, ret);
}
//实例1
//拦截消息,避免报unrecognized selector send to instance错误(只有方法声明,没有方法实现)
#pragma mark 方法签名
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
if ([self respondsToSelector:aSelector]) {
return [super methodSignatureForSelector:aSelector];
}
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
NSLog(@"找不到%@方法", NSStringFromSelector(anInvocation.selector));
}
//实例2
[super class]的底层实现
1:消息接收者仍然是子类对象
2:从父类开始查找方法的实现
- (Class)class {
return object_getClass(self);
}
//获取父类对象
- (Class)superclass {
return [self class]->superclass;
}
//Student继承Person
- (instancetype)init
{
self = [super init];
if (self) {
NSLog(@"[self class] = %@", [self class]); //Student
NSLog(@"[self superclass] = %@", [self superclass]); //Person
NSLog(@"-----------------");
NSLog(@"[super class] = %@", [super class]); //Student
NSLog(@"[super superclass] = %@", [super superclass]); //Person
}
return self;
}
网友评论