类的原理分析(二)

94 阅读2分钟

clean memory & dirty memory

在WWDC中有介绍到clean memory和dirty memory的概念,在类的结构中对应class_ro_t和class_rw_t,上一篇中我们探索了属性在bit中的位置,在properties中都能找到,但没有找到属性address的位置。

class_rw_tp $3->ro()

image.png

image.png 按照同样的方法获取其中的ivarsp $6.ivars

image.png 打印其中的内容,可以看到当前定义的address属性

image.png

成员变量和属性的区别

通过clang查看生成的cpp文件,name属性被编译成_name的成员变量,属性被注释

image.png

不同的是属性同时生成getter和setter方法

image.png 所以属性就是ivar + getter + setter

setProperty & 内存平移

在编译cpp中发现同样是属性,name调用的是setProperty方法而nickName的setter方法是内存平移的方式

image.png

这是在LLVM中做了优化,对用copy修饰的属性进行了objc_setProperty和objc_getProperty的方法调用,其中涉及到深拷贝和浅拷贝的问题。

类方法和元类

除了当前探索中的成员变量之外,还有一个当前没有找到的方法--类方法

对象方法和类方法可以重名,而对于底层而言并不区分对象方法和类方法,都是函数。那么如果都存储在类中,同名函数就无法区分是对象方法还是类方法,于是苹果通过元类来进行类方法的存储。

通过x/4gx拿到isa拿到元类

image.png

接着进行同分析类一样的操作

image.png 于是我们在元类中找到了类方法

除了用lldb查看相关的内容,可以通过runtime的方法直接获取相关内容。

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

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

从源码中可以看到获取类方法也是调用的class_getInstanceMethod, 说明不区分对象方法和类方法。