美文网首页
iOS - superclass 底层分析

iOS - superclass 底层分析

作者: felix6 | 来源:发表于2018-05-03 14:25 被阅读0次

    [toc]

    面试题

    先切入一个面试问题, 下面代码会输出什么?

    // Student: Person: NSObject
    - (instancetype)init {
        if (self = [super init]) {
            NSLog(@"[self class] = %@", [self class]); // Student
            NSLog(@"[self superclass] = %@", [self superclass]); // Person
    
            NSLog(@"--------------------------------");
    
            // objc_msgSendSuper({self, [Person class]}, @selector(class));
            // ({消息接收者, 消息接收者父类}, SEL)
            NSLog(@"[super class] = %@", [super class]); // Student
            NSLog(@"[super superclass] = %@", [super superclass]); // Person
        }
        return self;
    }
    

    底层分析

    OC代码

    // Student: Person: NSObject
    - (void)run {
        [super run]; // super调用的消息接收者仍然是 self (Student实例)
    }
    

    转成C++代码

    static void _I_Student_run(Student * self, SEL _cmd) {
        ((void (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Student"))}, sel_registerName("run"));
    } 
    
    // objc4/message.h
    id _Nullable objc_msgSendSuper(struct objc_super * _Nonnull super, SEL _Nonnull op, ...)
    

    上面代码拆解

    struct __rw_objc_super rcv = {
        self,
        class_getSuperclass(objc_getClass("Student"))
    }
    
    objc_msgSendSuper(rcv, @selector(run))
    
    objc_super

    __rw_objc_super 等价于 objc_super

    // objc4/message.h
    /// Specifies the superclass of an instance. 
    struct objc_super {
        /// Specifies an instance of a class.
        __unsafe_unretained _Nonnull id receiver; // 消息接收者
        
        __unsafe_unretained _Nonnull Class super_class; // 消息接收者的父类
        /* super_class is the first class to search */
    };
    
    class_getSuperclass()
    // objc4/runtime.h
    Class _Nullable class_getSuperclass(Class _Nullable cls)
    
    // objc4/objc-class.mm
    Class class_getSuperclass(Class cls) {
        if (!cls) return nil;
        return cls->superclass;
    }
    
    objc_msgSendSuper()

    可以看到, 使用 super 调用方法, 底层被转换成 objc_msgSendSuper()

    /** 
     * Sends a message with a simple return value to the superclass of an instance of a class.
     * 
     * @param super A pointer to an \c objc_super data structure. Pass values identifying the
     *  context the message was sent to, including the instance of the class that is to receive the
     *  message and the superclass at which to start searching for the method implementation. ★★
     * @param op A pointer of type SEL. Pass the selector of the method that will handle the message.
     * @param ...
     *   A variable argument list containing the arguments to the method.
     * 
     * @return The return value of the method identified by \e op.
     * 
     * @see objc_msgSend
     */
    // super 里封装了消息接收者(方法调用者) 和 消息接收者的父类
    id _Nullable objc_msgSendSuper(struct objc_super * _Nonnull super, SEL _Nonnull op, ...)
    

    苹果注释说, superclass 的作用是从哪里开始查找方法实现; 即从 objc_super.super_class 开始查找,

    所以, super 调用会直接从父类开始查找方法的实现

    [super funcName];

    而super调用的消息接收者仍然是子类对象, 只不过是从父类从开始查找方法的实现

    相当于还是self在调用方法

    objc_msgSendSuper2

    而打断点分析汇编, 可以看到, 实际真正调用的是 objc_msgSendSuper2

    // objc4/objc-abi.h
    // objc_msgSendSuper2() takes the current search class, not its superclass.
    id _Nullable objc_msgSendSuper2(struct objc_super * _Nonnull super, SEL _Nonnull op, ...);
    
    struct objc_super2 {
        id receiver; // 消息接收者
        Class current_class; // 当前类, 即receiver的Class对象
    };
    
    汇编实现

    该方法会拿到当前类, 在内部根据class找到superclass, 然后开始查找方法实现, 实际效果和 objc_msgSendSuper 是一样的

    ENTRY _objc_msgSendSuper2
    UNWIND _objc_msgSendSuper2, NoFrame
    
    ldp p0, p16, [x0]       // p0 = real receiver, p16 = class
    ldr p16, [x16, #SUPERCLASS] // p16 = class->superclass
    CacheLookup NORMAL, _objc_msgSendSuper2
    
    END_ENTRY _objc_msgSendSuper2
    

    class 和 superclass 方法

    每个OC类都有class方法, 可想而知, class 的方法实现在 NSObject 上, 所以不管 self调用, 还是super调用, 最终都是在 NSObject 上找到

    // objc4/NSObject.mm
    + (Class)class {
        return self;
    }
    
    - (Class)class {
        return object_getClass(self);
    }
    
    + (Class)superclass {
        return self->superclass;
    }
    
    // class_getSuperclass(object_getClass(self));
    - (Class)superclass {
        return [self class]->superclass;
    }
    

    superclass 指针

    class 对象的 superclass 指针
    image
    meta-class 对象的 superclass 指针
    image

    相关文章

      网友评论

          本文标题:iOS - superclass 底层分析

          本文链接:https://www.haomeiwen.com/subject/rogkrftx.html