005:类原理分析下
问题
目录
1:class_ro_t-->>class_rw_t-->>class_rw_ext_t
2:iskindOfClass & isMemberOfClass 的理解
3:class_getClassMethod源码
预备
正文
1:class_ro_t-->>class_rw_t-->>class_rw_ext_t
1.1:当类第一次从磁盘加载到内存,编译的时候,为class_ro_t

1.2:第一次使用runtime的时候是class_rw_t

1.3:将需要动态更新的部分提取出来,class_rw_ext_t
2: 简单面试题
1:类存在几份?
由于类的信息在内存中永远只存在一份,所以 类对象只有一份
2: objc_object 与 对象的关系
所有的对象 都是以 objc_object为模板继承过来的
所有的对象 是 来自 NSObject(OC) ,但是真正到底层的 是一个objc_object(C/C++)的结构体类型
【总结】 objc_object 与 对象的关系 是 继承关系
3:什么是 属性 & 成员变量 & 实例变量 ?
-
属性(property):在OC中是通过@property开头定义,且是带下划线成员变量+setter+getter方法的变量 -
成员变量(ivar):在OC的类中{}中定义的,且没有下划线的变量 -
实例变量:通过当前对象类型,具备实例化的变量,是一种特殊的成员变量,例如 NSObject、UILabel、UIButton等
【附加】成员变量 和 实例变量什么区别?
-
实例变量(即成员变量中的对象变量就是实例变量):以实例对象实例化来的,是一种特殊的成员变量 -
NSString是常量类型, 因为不能添加属性,如果定义在类中的{}中,是成员变量 -
成员变量中 除去基本数据类型、NSString,其他都是实例变量(即可以添加属性的成员变量),实例变量主要是判断是不是对象
3:class_getInstanceMethod和class_getClassMethod
class_getInstanceMethod:获取实例方法,如果指定的类或其父类不包含带有指定选择器的实例方法,则为NULL
class_getClassMethod:获取类方法,如果指定的类或其父类不包含具有指定选择器的类方法,则为NULL。class_getMethodImplementation:获取方法的具体实现,如果未查找到,则进行消息转发4:iskindOfClass & isMemberOfClass 的理解
@implementation LCPerson : NSObject BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]]; // 1 BOOL re2 = [(id)[LCPerson class] isKindOfClass:[LCPerson class]]; // 0 BOOL re3 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]]; // NSObject和实例的元类比较 NSObject 1 BOOL re4 = [(id)[LCPerson alloc] isKindOfClass:[LCPerson class]]; // 1 NSLog(@" re1 :%hhd\n re2 :%hhd\n re3 :%hhd\n re4 :%hhd\n",re1,re2,re3,re4); BOOL re5 = [(id)[NSObject class] isMemberOfClass:[NSObject class]]; // 0 BOOL re6 = [(id)[LCPerson class] isMemberOfClass:[LCPerson class]]; // 0 BOOL re7 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]]; // 1 BOOL re8 = [(id)[LCPerson alloc] isMemberOfClass:[LCPerson class]]; // 1 NSLog(@" re5 :%hhd\n re6 :%hhd\n re7 :%hhd\n re8 :%hhd\n",re5,re6,re7,re8);
3:源码解析
isKindOfClass 源码解析(实例方法 & 类方法)
//--isKindOfClass---类方法、对象方法 //+ isKindOfClass:第一次比较是 获取类的元类 与 传入类对比,再次之后的对比是获取上次结果的父类 与 传入 类进行对比
//判断的当前类的元类是否与条件类相等,如果不相等,会走当前类的元类的父类继续判断是否与条件类相等
+ (BOOL)isKindOfClass:(Class)cls { // 获取类的元类 vs 传入类 // 根元类 vs 传入类 // 根类 vs 传入类 // 举例:LGPerson vs 元类 (根元类) (NSObject) for (Class tcls = self->ISA(); tcls; tcls = tcls->superclass) { if (tcls == cls) return YES; } return NO; } //- isKindOfClass:第一次是获取对象类 与 传入类对比,如果不相等,后续对比是继续获取上次 类的父类 与传入类进行对比
//判断当前对象所属的类是否与条件类相等,如果不相等,会走当前对象所属的类的父类继续判断与条件类是否相等,是一个实例方法
- (BOOL)isKindOfClass:(Class)cls { /* 获取对象的类 vs 传入的类 父类 vs 传入的类 根类 vs 传入的类 nil vs 传入的类 */ for (Class tcls = [self class]; tcls; tcls = tcls->superclass) { if (tcls == cls) return YES; } return NO; }
isMemberOfClass 源码解析(实例方法 & 类方法)
//-----类方法 //+ isMemberOfClass : 获取类的元类,与 传入类对比 + (BOOL)isMemberOfClass:(Class)cls { return self->ISA() == cls; } //-----实例方法 //- isMemberOfClass : 获取对象的类,与 传入类对比 - (BOOL)isMemberOfClass:(Class)cls { return [self class] == cls; }
isKindOfClass(for循环)
- 类方法:
元类(isa) --> 根元类(父类) --> 根类(父类) --> nil(父类)与传入类的对比【判断元类】- 实例方法:
对象的类 --> 父类 --> 根类 --> nil与传入类的对比【判断实例所属的类】对象所属的类和对象实例的isa指针比较、
isMemberOfClass(不循环)
- 类方法:
类的元类与传入类对比【判断元类】- 实例方法:
对象的父类与传入类对比【判断实例所属的类】
类方法:判断的是isa,元类
实例方法判断的是都是通过[self class] 和自己的类来进行对比。永远是1.
iskindofClass有继承的关系。
3: class_getClassMethod 的源码:
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 Class getMeta() { if (isMetaClass()) return (Class)this; else return this->ISA(); }
class_getClassMethod的流程:
class_getClassMethod里面调用的也是class_getInstanceMethod;- 只不过传的类是
cls->getMeta()这个方法返回的; getMeta如果是元类,返回的就是自己;getMeta如果不是元类,返回的是ISA();- 类的
ISA()返回的是 该类的元类;
class_getClassMethod总结:
- 如果传的类,里面是获取的元类的
class_getInstanceMethod方法。也既类方法是从元类里面去找的。 - 如果传的是元类,直接用元类调用
class_getInstanceMethod方法。
注意
浙公网安备 33010602011771号