objc_msgSend执行流程

OC中的方法调用,其实都是转换为objc_msgSend函数的调用

objc_msgSend的执行流程可以分为3大阶段

  • 1.消息发送
  • 2.动态方法解析
  • 3.消息转发
1.消息发送

流程如下:


WechatIMG122.png

备注:

  • 在class_rw_t查找方法时,如果已经排序的,则二分查找提高效率, 如果没有排序的,遍历查找
  • receiver通过isa指针找到receiverClass
  • receiverClass通过superclass指针找到superClass
2.动态方法解析

流程如下
WechatIMG123.png
  • 动态解析过后,会重新走“消息发送”的流程“从receiverClass的cache中查找方法”这一步开始执行

示例
+resolveInstanceMethod:
+resolveClassMethod:
在上述两个方法中防止崩溃

@interface ClassA : NSObject
- (void)test;
@end

#import "ClassA.h"
#import 
@implementation ClassA

- (void)other {
    NSLog(@"在.m里没有实现test方法 正常情况下会报错, 但是在resolveInstanceMethod进行了处理就不会有问题了");
}

// 没找到对象方法的时候调用这个
+ (BOOL)resolveInstanceMethod:(SEL)sel {
    if (sel == @selector(logAAA)) {
        // 创建一个方法
        Method otherMethod = class_getInstanceMethod(self, @selector(other));
        
        class_addMethod(self, sel,
                        // 之前定义方法的实现
                        method_getImplementation(otherMethod),
                        // types
                        method_getTypeEncoding(otherMethod));
        return YES;
    }
    
    return  [super resolveInstanceMethod:sel];
}
@end

3.消息转发阶段

当实现过 2动态方法解析阶段, 会进入消息转发阶段


WechatIMG127.png

相关代码

- (id)forwardingTargetForSelector:(SEL)aSelector {
    
    return [super forwardingTargetForSelector:aSelector];
}

// 返回方法签名: 返回值类型, 参数类型
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    if (aSelector == @selector(test)) {
        return [NSMethodSignature signatureWithObjCTypes:@"v20@0:i16"];
    }
    return [super methodSignatureForSelector:aSelector];
}

// NSInvocation 封装了一个方法调动, 包括 方法调用者, 方法名, 方法参数
// anInvocation.selector 方法名
// anInvocation.target 方法调用者
- (void)forwardInvocation:(NSInvocation *)anInvocation {
    // 在这里修改 target 和selecor 从而实现消息发送
    anInvocation.target = [[ClassC alloc]init];
    anInvocation.selector = @selector(classCTest);
    [aninvocation invoke];
}

注意: 类方法的 消息转发阶段 全都是+方法

[self class] 和[super class]

1:底层实现

// self
objc_msgSend

// super
objc_msgSendSuper(self, @selector(class))

2:self和super的消息接收者都是当前类 例如, [self class]和 [super class] 消息接收者都是self 但是查找层级不同 self 从当前类查找, super 从父类查找

3: class 方法虽然每个oc对象都有声明, 但是具体实现是在NSObject里面

NSObject中class的实现 大体是

- (Class)class 
{
   return object_getClass(self);
}

- (Class)superClass 
{
   return object_getSuperclass(self);
}

结论: 由源码可以看出 class和superClass 的消息接收者都是self

迁移

@interface Person : NSObject

@end

@interface Student : Person

@end

@implementation Student

- (instancetype)init
{
    self = [super init];
    if (self) {
        NSLog(@"%@", [self class]);  Student
        NSLog(@"%@", [self superclass]); Person

        NSLog(@"%@", [super class]); Student
        NSLog(@"%@", [super superclass]);   Person     
    }
    return self;
}

@end

上述示例中, 无论 suerp 还是self 他们的class 和superClass 方法的实现都在 NSObject当中, 所以他们的消息接收者都是self, 只不过super 是从Person开始查找, self 是从Student中开始查找

你可能感兴趣的:(objc_msgSend执行流程)