OC 底层iOS面试题+基础知识iOS-Runtime

iOS 对类,元类,根元类关系图的验证

2018-06-11  本文已影响860人  陆离o

一.类,元类,根元类关系图

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


image.png

二.验证方法

1. 选择在ViewController里验证,导入头文件#import <objc/runtime.h>
2. 创建4个实例对象

2.1 创建NSObject实例对象

    NSObject *obj = [[NSObject alloc] init];

2.2 创建UIResponder实例对象

    UIResponder *responder = [[UIResponder alloc] init];

2.2 创建UIView实例对象

    UIView *view = [[UIView alloc] init];

2.2 创建自定义的ShapeView类(继承UIView)的实例对象

    ShapeView *shape = [[ShapeView alloc] init];
3.通过object_getClass获取对象isa指针指向链。
 Class cls = object_getClass(shape);
//metaClass
Class metaCls1 = object_getClass(cls);
Class metaCls2 = object_getClass(metaCls1);
Class metaCls3 = object_getClass(metaCls2);
Class metaCls4 = object_getClass(metaCls3);

object_getClass参数是id类型,它返回的是这个id的isa指针所指向的Class,如果传参是Class,则返回该Class的metaClass。

Class object_getClass(id obj)
{
    if (obj) return obj->getIsa();
    else return Nil;
}

class中也包含了isa指针,通过class的isa找到对应的元类meta-class:

struct objc_class {
    Class isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class super_class                                        OBJC2_UNAVAILABLE;
    const char *name                                         OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;
4.通过class_getSuperclass方法获取对象的继承链。
//superClass
Class superCls1 = class_getSuperclass(cls);
Class superCls2 = class_getSuperclass(superCls1);
Class superCls3 = class_getSuperclass(superCls2);
Class superCls4 = class_getSuperclass(superCls3);

三.根据打印的内存地址绘制关系图

可以看到,绘制的关系图和上图是一致,但更加形象。
image.png

四.总结

1.方法调用。对象调用实例方法时,是在对应类对象及其继承链上找方法。类对象调用类方法时,是在其元类及继承链上找方法。
2.内存布局。NSObject类,UIResponder类,UIView类(绿框内的类)在app启动时已经完成内存布局,所以不同实例对象对应的类,父类,元类打印出来的地址相同。
image.png
3.所以元类的isa指针都指向根元类(NSObject),根元类的isa指针指向自己。
上一篇 下一篇

猜你喜欢

热点阅读