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开头定义,且是带下划线成员变量settergetter方法的变量

  • 成员变量(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的流程:

  1. class_getClassMethod里面调用的也是 class_getInstanceMethod;
  2. 只不过传的类是 cls->getMeta()这个方法返回的;
  3. getMeta如果是元类,返回的就是自己;
  4. getMeta如果不是元类,返回的是 ISA();
  5. 类的 ISA()返回的是 该类的元类;

class_getClassMethod总结

  • 如果传的类,里面是获取的元类的 class_getInstanceMethod方法。也既类方法是从元类里面去找的。
  • 如果传的是元类,直接用元类调用 class_getInstanceMethod方法。

注意

 

引用

1:iOS 类的结构分析(下)

2:图解isKindOfClass和isMemberOfClass

 3:iOS中经典面试题的分析和总结

posted on 2020-11-30 18:44  风zk  阅读(136)  评论(0编辑  收藏  举报

导航