OC 类的底层实现

2019-03-11  本文已影响0人  我是晶锅

类的底层结构

和对象的底层一样,类对象前八个字节也是存的isa指针,那么第二个字节表示什么,我们可以直接找到源码,查看类结构。

class_rw_t的结构

bits中返回了data,data的结构是class_rw_t,我们查看其中是什么样的结构,不进去不知道,一进去吓一跳,里面全是我们这个类中重要的信息。
调试时怎么进去呢?
通过类对象执行偏移进去的,想要进去data中的部分,将类对象指针向前偏移两位就可以了。
先看看其中结构吧:

image.png

没错,这里面有方法列表,属性列表,协议列表。
这里需要注意一下,readonly的属性和相关不可更改的都存在这里,这里的部分是不能进行修改的,当一个类创建完成的时候。
所以,类创建完成后,是不能添加ivar的了!


image.png

LLDB调试验证

看了源码中的代码,现在我们直接通过LLDB来调试验证正确性。
在已经导入源码的情况下,调试可以拿到底层数据结构中的对象。
1、拿到类对象,指针偏移两位,获取到data
2、打印data中所有数据,你能看到这个类的基本方法列表,属性列表和协议列表了


image.png

继续往里走,可以拿到我们自己创建的方法


image.png
通过这样的方式,我们还可以验证两个东西:

打印验证方法的获取

上面我们能够通过LLDB直接查看方法存的位置,类方法存在元类中,实例方法存在类中。(0表示有,1表示没有)
LGPerson中书写两个方法,并实现:

- (void)lg_instanceMethod;
+ (void)lg_classMethod;
demo1:class_getInstanceMethod
    Method method1 = class_getInstanceMethod([LGPerson class], @selector(lg_instanceMethod)); // 类对象 拿 实例方法
    Method method2 = class_getInstanceMethod(objc_getMetaClass("LGPerson"), @selector(lg_instanceMethod)); // 元类对象 拿 实例方法
    Method method3 = class_getInstanceMethod([LGPerson class], @selector(lg_classMethod));
    Method method4 = class_getInstanceMethod(objc_getMetaClass("LGPerson"), @selector(lg_classMethod));
    NSLog(@"%p-%p-%p-%p",method1,method2,method3,method4);

这里输出:1 0 0 1
解释:
对象方法是存在类中的,method1为1,method2为0;
类方法存在元类中的,method3为0,method4为1。

demo2:class_getMethodImplementation
    IMP imp1 = class_getMethodImplementation([LGPerson class], @selector(lg_instanceMethod));
    IMP imp2 = class_getMethodImplementation([LGPerson class], @selector(lg_classMethod));
    IMP imp3 = class_getMethodImplementation(objc_getMetaClass("LGPerson"), @selector(lg_instanceMethod));
    IMP imp4 = class_getMethodImplementation(objc_getMetaClass("LGPerson"), @selector(lg_classMethod));
    NSLog(@"%p-%p-%p-%p",imp1,imp2,imp3,imp4);

这里输出:1 1 1 1
解释:imp1 和 imp4与上面同理。为什么imp2 和 imp3也会有呢?其实类中并没有类方法,元类中也没有对象方法,只是 class_getMethodImplementation 底层会走 _objc_msgForward 方法,所以还是找到了。


image.png
demo3:class_getClassMethod
    Method method1 = class_getClassMethod([LGPerson class], @selector(lg_instanceMethod));
    Method method2 = class_getClassMethod(objc_getMetaClass("LGPerson"), @selector(lg_instanceMethod));
    
    // 类 --> lg_classMethod 类方法
    // 元类
    Method method3 = class_getClassMethod([LGPerson class], @selector(lg_classMethod));
    Method method4 = class_getClassMethod(objc_getMetaClass("LGPerson"), @selector(lg_classMethod));
    NSLog(@"%p-%p-%p-%p",method1,method2,method3,method4);

输出:0 0 1 1
解释:我们从底层源码中看出,class_getClassMethod 底层使用就是 class_getInstanceMethod

Method class_getClassMethod(Class cls, SEL sel)
{
    if (!cls  ||  !sel) return nil;

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

所以 method1 和 method2 中根本没有 lg_instanceMethod 的类方法,lg_instanceMethod 是一个对象方法。
method3 和 method4 其实都是从元类中找寻类方法,所以当然能找到。

添加方法,协议,属性 attachLists

我们的类,在创建类和需要添加的时候都会调用 attachLists 方法,将我们需要添加的方法,协议,属性添加进去。具体 attachLists 是怎么实现的,接下来分解。


image.png

最后附上一张类的底层结构图:


类结构.png
上一篇下一篇

猜你喜欢

热点阅读