美文网首页
iOS 对实例、类对象、元类、根元类验证

iOS 对实例、类对象、元类、根元类验证

作者: 年轻就要活出样 | 来源:发表于2019-08-15 15:01 被阅读0次

精华Pod库分享

一、类、根类、元类、根元类关系图

网上流传一张类,元类,根元类的关系图。详细描述了它们相互间的继承关系和isa指向关系。下面用代码对这张图进行验证。


屏幕快照 2019-08-14 下午4.46.13.png

二、验证关系

验证之前我们了解一下两个runtime函数

  • class_getSuperclass()
    • 通过object_getClass获取对象isa指针指向链。
      object_getClass参数是id类型,它返回的是这个id的isa指针所指向的Class,如果传参是Class,则返回该Class的metaClass。
  • object_getClass()
    • 通过class_getSuperclass方法获取对象的继承链。
      class_getSuperclass 参数是Class类型,它返回的是该Class的superClass指针指向的Class。

Person 类继承自NSObject

 Person *p           = [Person new];
    Class  class1       = object_getClass(p); // 获取p ---> 类对象
    Class  class2       = [p class];  // 获取p ---> 类对象
    NSLog(@"class1 === %p class1Name == %@ class2 === %p class2Name == %@",class1,class1,class2,class2);
    
    /** 元类查找过程 */
    Class  class3       = objc_getMetaClass(object_getClassName(p)); // 获取p ---> 元类
    NSLog(@"class3 == %p class3Name == %@",class3,class3);
    
    Class  class4       = objc_getMetaClass(object_getClassName(class3)); // 获取class3 ---> 元类  此时的元类,class4就是根元类。
    NSLog(@"class4 == %p class4Name == %@",class4,class4); // class4 == 0x106defe78 class4Name == NSObject
    
    
    /** 元类查找结束,至此。我们都知道 根元类 的superClass指针是指向 根类对象 的;根类对象的isa指针有指向根元类对象;根元类对象的isa指针指向根元类自己;根类对象的superClass指针指向nil */
    Class  class5       = class_getSuperclass(class1);  // 获取 类对象的父类对象
    NSLog(@"class5 == %p class5Name == %@",class5,class5);  //class5 == 0x106defec8 class5Name == NSObject

    // 此时返现class5 已经是NSObject,我们再次获取class5的父类,验证class5是否是 根类对象
    Class  class6       = class_getSuperclass(class5);  // 获取 class5的父类对象
    NSLog(@"class6 == %p class6Name == %@",class6,class6); // class6 == 0x0 class6Name == (null) 至此根类对象验证完毕。
    
    
    /** 验证根类对象与根元类对象的关系 */
    Class  class7       = objc_getMetaClass(object_getClassName(class5)); // 获取根类对象 对应的  根元类 是否是class4 对应的指针地址
    NSLog(@"class7 == %p class7Name == %@",class7,class7);  // class7 == 0x106defe78 class7Name == NSObject
    
    Class  class8      =  class_getSuperclass(class4);  // 获取根元类class4  superClass 指针的指向 是否是根类对象class5 的指针地址
    NSLog(@"class8 == %p class8Name == %@",class8,class8);  // class8 == 0x106defec8 class8Name == NSObject; class8与class5指针地址相同
    
    Class  class9       = objc_getMetaClass(object_getClassName(class4)); // 获取根元类 isa 指针是否是指向自己
    NSLog(@"class9 == %p class9Name == %@",class9,class9);  //  class9 == 0x106defe78 class9Name == NSObject; class9 与 class4、class7指针地址相同

结果

由上运行结果可知:


屏幕快照 2019-08-15 下午1.56.59.png
  • 实例对象:p
  • 类对象 :class1、class2
  • 元类对象:class3
  • 根元类 : class4、class7、calss9
  • 根类对象:class5、calss8

总结图

屏幕快照 2019-08-15 下午2.56.02.png

三、iOS中的 isKindOfClass 和 isMemberOfClass区别?

逆向实现

  • 如下,Person继承自NSObject,[Person class]的地址,就是Person实例的类对象地址。
 Person *son = [Person new];
    Class class1 = object_getClass(son);
    NSLog(@"%p  ===   %p   ====   %p  ==== %p",class1,[son class],[Person class],son);
打印结果:
2019-09-20 15:24:50.777969+0800 sortTime[3041:228435] 
0x105248970  ===   0x105248970   ====   0x105248970  ==== 0x600001628930
  • 列子
    BOOL res1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
    BOOL res2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];
    BOOL res3 = [(id)[Sark class] isKindOfClass:[Sark class]];
    BOOL res4 = [(id)[Sark class] isMemberOfClass:[Sark class]];
    BOOL res5 = [(id)[Sark class] isKindOfClass:[NSObject class]];
    BOOL res6 = [(id)[Sark class] isMemberOfClass:[NSObject class]];

打印结果:
2019-09-20 15:10:22.235225+0800 sortTime[2852:215634] 1 0 0 0 1 0
  • 验证 [(id)[NSObject class] isKindOfClass:[NSObject class]]返回YES
    详解
    • isKindOfClass内部实现
 //逆向反编译得到的源码
- (BOOL) isKindOfClassITX:(Class)class
{
    NSLog(@"class->%@:%p",NSStringFromClass(class), class);
    NSLog(@"%p",[NSObject class]);

    Class r0 = object_getClass(self);
    
    while (1) {
        if (r0 == 0) {
            return 0;
        }else{
            NSLog(@"r0->%@:%p",NSStringFromClass(r0), r0);
            if (r0 != class) {
                r0 = [r0 superclass];
            }else{
                return 1;
            }
        }
    }
}
  • 验证结果
 BOOL res7 = [(id)[NSObject class] isKindOfClassITX:[NSObject class]];
    NSLog(@"%d",res7);
2019-09-20 15:28:49.632315+0800 sortTime[3104:232025] class->NSObject:0x10ec42ec8
2019-09-20 15:28:49.632647+0800 sortTime[3104:232025] 0x10ec42ec8
2019-09-20 15:29:34.024142+0800 sortTime[3104:232025] r0->NSObject:0x10ec42e78
2019-09-20 15:29:40.357044+0800 sortTime[3104:232025] r0->NSObject:0x10ec42ec8
  • 总结:
    (1)、1号[NSObject class](类对象)对应的元类(根元类)对象和2号[NSObject class](类对象,也是根类对象)比较是否相等,如果不等.
    (2)、1号对象元类superClass指针指向的父类(此时的父类是根类对象)和2号[NSObject class](类对象,也是根类对象)比较是否相等,此时相等。

    Snip20190920_1.png
  • 验证 [(id)[Sark class] isKindOfClass:[NSObject class]]返回YES

    • 验证结果
  BOOL res7 = [(id)[Person class] isKindOfClassITX:[NSObject class]];
    NSLog(@"%d",res7);
2019-09-20 16:11:43.234421+0800 sortTime[3541:269003] class->NSObject:0x101a32ec8
2019-09-20 16:11:43.234500+0800 sortTime[3541:269003] 0x101a32ec8
2019-09-20 16:11:43.234565+0800 sortTime[3541:269003] 0x1009df9a8
2019-09-20 16:11:48.343621+0800 sortTime[3541:269003] r0->Person:0x1009df980
2019-09-20 16:11:48.343945+0800 sortTime[3541:269003] r0->NSObject:0x101a32e78
2019-09-20 16:11:48.344146+0800 sortTime[3541:269003] r0->NSObject:0x101a32ec8
  • 总结:
    (1)、1号[Person class](类对象)对应的元类3号(元类)对象和2号[NSObject class](根类对象)比较是否相等,此时不等.
    (2)、3号对象superClass指针指向的父类4号对象(此时的父类是根元类对象)和2号[NSObject class](根类对象)比较是否相等,此时不等。
    (3)、4号对象(根元类)superClass指向的父类5号对象(根类对象)和2号[NSObject class](根类对象)比较是否相等,此时相等。

    Snip20190920_2.png
  • 验证 [[Person new] isKindOfClassITX:[NSObject class]]返回YES

    • 验证结果
BOOL res7 = [[Person new] isKindOfClassITX:[NSObject class]];
NSLog(@"%d",res7);
2019-09-20 16:41:06.241951+0800 sortTime[3781:288460] class->NSObject:0x10f2c0ec8
2019-09-20 16:41:06.242027+0800 sortTime[3781:288460] 0x10f2c0ec8
2019-09-20 16:41:06.242092+0800 sortTime[3781:288460] 0x60000326c520
2019-09-20 16:41:11.159426+0800 sortTime[3781:288460] r0->Person:0x10e26d9a8
2019-09-20 16:41:11.159572+0800 sortTime[3781:288460] r0->NSObject:0x10f2c0ec8
  • 总结:
    (1)、1号[Person new](实例)对应的元类3号(类对象)对象和2号[NSObject class](根类对象)比较是否相等,此时不等.
    (2)、3号对象superClass指针指向的父类4号对象(此时的父类是根类对象)和2号[NSObject class](根类对象)比较是否相等,此时相等等。
    Snip20190920_3.png

isMemberOfClass

isMemberOfClass的源码实现是拿到自己的isa指针和自己比较,是否相等。

相关文章

  • iOS 对实例、类对象、元类、根元类验证

    精华Pod库分享 tableveiw 刷新控件 VNHttpRequest 一、类、根类、元类、根元类关系图 网上...

  • 类的结构分析

    对象、类、元类、根元类 对象是类的实例,对象是以类为模版来创建的。类的实质上也是一个对象,类是元类的实例对象。类对...

  • 类对象、元类

    任何实例的isa指针指向其类对象,类对象的isa指针指向其元类对象,元类对象的isa指针指向根元类对象,根元类对象...

  • iOS开发中方法查找流程图

    实例对象的isa指针指向类对象,类对象的isa指针指向元类,元类的isa指针指向根元类,根元类的isa指针指向自己...

  • 3.isa

    isa指向 ->实例isa -> 类|类isa -> 元类 | 元类isa -> 根元类|根元类isa -> 根元...

  • isa的流程和类的继承

    isa的指向流程: NSObejct:实例对象的isa指向 元类,元类的isa指向根元类,根元类的isa指向自己 ...

  • iOS 的实例对象、类、元类

    级别:★★☆☆☆标签:「实例对象」「类」「元类」「实例对象、类、元类」作者: ITWYW[https://www....

  • isa指针的作用

    原文:iOS面试题大全 对象的isa指向类,类的isa指向元类(meta class),元类isa指向元类的根类。...

  • iOS类的结构分析

    一、实例对象、类、元类关系分析 1. 实例对象、类、元类关系图解析 我相信上面这张经典的实例对象、类、元类关系图大...

  • isa 和 superclass

    实例对象的 isa 指向类对象,类对象的 isa 指向元类对象,元类的isa 指向基类的元类对象,基类的元类对象的...

网友评论

      本文标题:iOS 对实例、类对象、元类、根元类验证

      本文链接:https://www.haomeiwen.com/subject/vulzjctx.html