在Object-c中,实例对象的isa指向类对象,类对象的isa指向元类对象。也就是说调用实例对象的方法会查找类中的方法,调用类对象方法会在查找元类中的方法。
Person * person = [[Person alloc] init];
[person instanceMethodSelf];//实例方法
[Person classMethodSelf];//类方法
RunTime源码阅读(六)之消息查找方法最终会调用lookUpImpOrForward。
在实例方法调用时,断点看到cls已经是Person类 类方法
类方法中的cls已经是一串地址了。而这串地址就是objc_getMetaClass("Person")打印的元类地址。
截屏2020-01-27上午10.39.40.png
至此证明了:实例方法是调用类中的方法,类方法调用的是元类的方法。
class_getInstanceMethod:获取实例方法
Method addMethod = class_getInstanceMethod(self, @selector(addDynamicInstanceMethodAfter));//方法的二分查找,self当前类对象
class_getInstanceMethod在静态方法中调用时,self就是当前类。关于证明可以参考这篇文章:iOS 实例方法和类方法中的self与self.class有什么区别?
class_getClassMethod:获取类方法
Method class_getClassMethod(Class cls, SEL sel)
{
if (!cls || !sel) return nil;
//getMeta对isa查找的封装,如果是元类返回self,如果是类则返回isa。与self.class查找有点像
return class_getInstanceMethod(cls->getMeta(), sel);//cls->getMeta()不是类对象,是元类
}
class_getClassMethod:中调用是直接获取cls->getMeta()
总结:
- 无论是从方法调用,还是从获取类方法和实例方法。系统内部已经自动处理了isa指针,无需开发者处理。
- 为什么实例对象方法存在类对象,类对象方法存在元类中?
个人理解:这只是一种实现的形式:实例对象方法是一直存在的,不可能随着变量的生命周期而产生和销毁。对象分配会增加和减少内存,但对象的方法属性是固定的。找个媒介存放而已。
实例对象和类对象本质是一样的,都是方法。类对象的与实例对象相比,没有生命周期,只有静态方法而言,相当于是阉割版的实例方法。
网友评论