2021-04-01  本文已影响0人  雷霸龙

1、元类

关系链:对象 --> 类 --> 元类 --> NSobject,NSObject指向自身

2、NSObject到底有几个?

最后NSObject类的元类也是NSObject,内存中只存在一份根元类NSObject,根元类的元类是指向它自己

[面试题]:类存在几份?

由于类的信息在内存中永远只存在一份,所以类对象只有一份

3、著名的isa走位和继承关系图

image.png
isa走位
superclass走位(即继承关系)

类之间的继承关系:

元类也存在继承,元类之间的继承关系如下:

注意:实例对象之间没有继承关系,类之间有继承关系

4、objc_class & objc_object

为什么对象和类都有isa属性呢?这里就不得不提到两个结构体类型:objc_class & objc_object

NSObject的底层编译是NSObject_IMPL结构体,其中 Class是isa指针的类型,是由objc_class定义的类型,而objc_class是一个结构体。在iOS中,所有的Class都是以 objc_class 为模板创建的

struct NSObject_IMPL {
    Class isa;
};


typedef struct objc_class *Class;
struct objc_object {
    Class _Nonnull isa __attribute__((deprecated));
};
objc_class 与 objc_object 有什么关系?
objc_object 与对象的关系

5、方法列表存储位置

6、什么是属性、成员变量、实例变量?

7、元类中为什么会有类对象的类方法?

lgObjc_copyMethodList函数分析

在这个函数中,主要是获取类中的方法列表,实例方法存储在类中,类方法存储在元类中

lgInstanceMethod_classToMetaclass函数分析

在分析前,需要先了解class_getInstanceMethod这个方法,主要是用于获取实例方法,如果在传入的类或者类的父类中没有找到指定的实例方法,则返回NULL

lgClassMethod_classToMetaclass函数分析

在分析前,需要先了解class_getClassMethod这个方法,主要是用于获取类方法,如果在传入的类或者类的父类中没有找到指定的类方法,则返回NULL

//获取类方法
Method class_getClassMethod(Class cls, SEL sel)
{
    if (!cls  ||  !sel) return nil;

    return class_getInstanceMethod(cls->getMeta(), sel);
}

//获取元类
 // NOT identical to this->ISA when this is a metaclass 判断是否是元类,是元类就直接返回,反之,继续找isa指向
Class getMeta() {
    if (isMetaClass()) return (Class)this;
    else return this->ISA();
}

看该方法的源码实现,可以得出class_getClassMethod的实现是获取类的类方法,其本质就是获取元类的实例方法,最终还是会走到class_getInstanceMethod,但是在这里需要注意的一点是:在getMeta源码中,如果判断出cls是元类,那么就不会再继续往下递归查找,会直接返回this,其目的是为了防止元类的无限递归查找

源码流程图如下所示

image.png
lgIMP_classToMetaclass函数分析

class_getMethodImplementation 主要是返回方法的具体实现

IMP class_getMethodImplementation(Class cls, SEL sel)
{
    IMP imp;

    if (!cls  ||  !sel) return nil;

    //查找方法实现
    imp = lookUpImpOrNil(nil, sel, cls, LOOKUP_INITIALIZE | LOOKUP_RESOLVER);

    //如果没有找到,则进行消息转发
    if (!imp) {
        return _objc_msgForward;
    }

    return imp;
}

该函数在向类实例发送消息时会被调用,并返回一个指向方法实现函数的指针。这个函数会比method_getImplementation(class_getInstanceMethod(cls, name))更快。返回的函数指针可能是一个指向runtime内部的函数,而不一定是方法的实际实现。如果类实例无法响应selector,则返回的函数指针将是运行时消息转发机制的一部分

总结:
上一篇 下一篇

猜你喜欢

热点阅读