isa和superClass

Objective-C的本质

我们平时编写的Objective-C代码,底层实现其实都是C\C++代码,Objective-C的对象、类主要是基于C\C++的结构体实现的

调用关系.png

将Objective-C代码转换为C\C++代码:
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc OC源文件 -o 输出的CPP文件
如果需要链接其他框架,使用-framework参数。比如-framework UIKit

一个OC对象在内存中是如何布局的?
NSObject的底层实现.png

OC对象的分类主要分为三个大类

实例对象,instance对象就是通过类alloc出来的对象,每次调用alloc都会产生新的instance对象object1、object2是NSObject的instance对象(实例对象)
// instance对象,实例对象
NSObject *object1 = [[NSObject alloc] init];
NSObject *object2 = [[NSObject alloc] init];

它们是不同的两个对象,分别占据着两块不同的内存
instance对象在内存中存储的信息包括

  • isa指针
  • 其他成员变量
实例对象地址.png
类对象objectClass1 ~ objectClass5都是NSObject的class对象(类对象)
// class对象,类对象
// class方法返回的一直是class对象,类对象
Class objectClass1 = [object1 class];
Class objectClass2 = [object2 class];
Class objectClass3 = object_getClass(object1);
Class objectClass4 = object_getClass(object2);
Class objectClass5 = [NSObject class];

它们是同一个对象。每个类在内存中有且只有一个class对象

class对象在内存中存储的信息主要包括

  • isa指针

  • superclass指针

  • 类的属性信息(@property)、类的对象方法信息(instance method)

  • 类的协议信息(protocol)、类的成员变量信息(ivar)
    ......

  • 类方法信息


    类对象结构.png
元类对象

每个类在内存中有且只有一个元类对象,元类对象和类对象的内存结构一样,但用途不一样。

元类对象在内存中存储的信息

  • isa指针
  • superClass的isa指针
元类对象结构.png
// meta-class对象,元类对象
// 将类对象当做参数传入,获得元类对象
Class objectMetaClass = object_getClass(objectClass5);
类的获取

Class objc_getClass(const char *aClassName)
传入字符串类名
返回对应的类对象

Class object_getClass(id obj)
传入的obj可能是instance对象、class对象、meta-class对象

返回值
如果是instance对象,返回class对象
如果是class对象,返回meta-class对象
如果是meta-class对象,返回NSObject(基类)的meta-class对象

(Class)class、+ (Class)class
返回的就是类对象

\color{red}{实例对象的isa指向的是类对象,类对象的isa指向的是元类对象}

指针

isa

instance的isa指向class
当调用对象方法时,通过instance的isa找到class,最后找到对象方法的实现进行调用

class的isa指向meta-class
当调用类方法时,通过class的isa找到meta-class,最后找到类方法的实现进行调用

isa指针.png
supclass

supclass指针指向父类的类对象

class对象的superclass指针
当Student的instance对象要调用Person的对象方法时,会先通过isa找到Student的class,然后通过superclass找到Person的class,最后找到对象方法的实现进行调用

class的supclass.png

meta-class对象的superclass指针
当Student的class要调用Person的类方法时,会先通过isa找到Student的meta-class,然后通过superclass找到Person的meta-class,最后找到类方法的实现进行调用


meta-class的superclass.png
占用内存

创建一个实例对象,至少需要多少内存?

#import <objc/runtime.h>
class_getInstanceSize([NSObject class]);

创建一个实例对象,实际上分配了多少内存?

#import <malloc/malloc.h>
malloc_size((__bridge const void *)obj);

isa指针占用8个字节,_no占用4个字节,_age占用4个字节


student对象内部结构.png

总结

instance的isa指向class
class的isa指向meta-class
meta-class的isa指向基类的meta-class

class的superclass指向父类的class,如果没有父类,superclass指针为nil
meta-class的superclass指向父类的meta-class,基类的meta-class的superclass指向基类的class

instance调用对象方法的轨迹,isa找到class,方法不存在,就通过superclass找父类
class调用类方法的轨迹,isa找meta-class,方法不存在,就通过superclass找父类

指针路径.png

\color{red}{64bit之后,isa指针要 \& ISA\_MASK}

ISA_MASK值.png

isa指向地址获取流程如下图


isa指向地址获取.png

\color{red}{superClass指针是直接指向父类的类对象的}

  • 对象调用方法的轨迹

    通过isa指针指向类对象,在类对象的实例方法列表中找,如果没找到,通过superclass指针向父类里面找,若果都没有找到,则会报错:No known class method for selector

  • 类对象调用方法的轨迹

    和对象调用方的轨迹类似,只不过是对象通过isa找到类对象,类对象通过isa找到元类对象,依次向上找,找到基类元类对象里面,如果基类元类对象里面也没有的话,会去基类的类对象里面找

    举例说明:
    对象中没有类方法 +test(),但是父类中有实例方法 -test(),这个时候调用 [Person test],会依次向上查找,直到再父类类对象中找到实例方法,可以调用
    消息传递方式
    objc_msgSend([Person class], @selector(test))
    objc_msgSend(person, @selector(test))
    isa -> superclass -> suerpclass -> superclass -> .... superclass == nil
    

objc_object结构

objc_object结构.png
struct objc_class {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;

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

} OBJC2_UNAVAILABLE;

当前使用的都是OBJC2,所以这段结构基本上废弃了,现在为以下结构:

struct objc_class {
    Class isa;
    Class superclass;
    cache_t cache;  //方法缓存,是个table
        class_data_bits_t bits;  //  用于获取具体的类信息,是个table
}

& FAST_DATA_MASK  之后获得

struct class_rw_t {
    uint32_t
        Class isa;
        Class superclass;
        cache_t cache;  //方法缓存,是个table
        class_data_bits_t bits;  //  用于获取具体的类信息,是个table
}

总结

  • 对象的指针指向哪里
    对象的isa指针指向类对象
    类对象的isa指针指向元类的类对象
    元类类对象的isa指针指向基类的元类类对象

  • OC的类信息存放在哪里
    实例对象方法、属性、成员变量(大小,类型,名字)、协议信息存放在类对象中
    类方法存放在元类对象中
    成员变量的具体值存放在实例对象

objc4源码下载

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,542评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,822评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,912评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,449评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,500评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,370评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,193评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,074评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,505评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,722评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,841评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,569评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,168评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,783评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,918评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,962评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,781评论 2 354

推荐阅读更多精彩内容