用代码验证类方法的归属和存储(结合isa走位图)

前面的文章我们讲到了如何通过isa指针以及指针位移的方式拿到实例方法和类方法,下面我们再通过代码来验证这一结果。在runtime里苹果提供了两个方法,这两个方法在方法替换的时候也会用到:

1、class_getInstanceMethod:获取实例方法

2、class_getClassMethod:获取类方法

class_getInstanceMethod使用

在使用class_getInstanceMethod获取实例方法时,method1和method4是有值的,method2是在元类去找,根据我们之前的推导,实例方法是存在类里,这也证明了我们之前的结论。method4是有值的,证明类就是元类的实例,类方法存在元类中

class_getClassMethod使用

在使用class_getClassMethod获取类方法时候,method1和method2都为空,这里毋庸置疑。method3和method4有值且相等,我们可以通过源码得到class_getClassMethod的实现:

class_getClassMethod内部

class_getClassMethod里实际又会调用class_getInstanceMethod,并用元类(getMeta)作为入参。

通过以上截图可以得到,getMeta()函数里会递归调用isMetaClass(),如果已经是元类则返回自己。所以在使用class_getClassMethod获取类方法时,实际是在元类里寻找实例方法,根据我们第一步里的分析的结果,这里是可以获取到的,而且传入的参数不管是类还是元类,找到的结果都一样。

结论:实例方法存在类中,类方法存在元类中


////////补充////////

3、class_getMethodImplementation:获取方法的调用地址

思考下这里的imp2和imp3为什么会有值?我们来分析下源码:

当imp为空时,会返回_objc_msgForward...,_objc_msgForward(消息转发)相关内容待后续挖掘...

下面我们再结合isa走位图,看如下情况:

ClassA头文件
NSObject分类
在AppDelegate里执行方法调用是否会崩?
在AppDelegate里执行方法调用是否会崩?
isa走位图

通过isa走位图,我们可以知道实例(对象)方法是存在类里,类方法是存在元类里,类方法是以实例(对象)方法的形式存在于元类里。当找不到方法时会去父类寻找,最后都会到NSObject里去找。所以以上两种调用都不会崩溃,且能成功找到方法。

如果把分类里的方法改成类方法,就会发生崩溃。原因如上:类方法是以实例(对象)方法的形式存在于元类里

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容