OC底层原理:对象、类、isa 逻辑梳理

OC底层原理 学习大纲

我们已经从底层熟悉了对象isa。但碎片化的知识让我有点头晕。 学着学着发现,我不知道如何用语言来完整的描述他们了。

为了避免造成邯郸学步的惨剧。

现在,我将以上帝视角来梳理一下他们之间的关系。

在了解之前,如果你还不了解isa结构类的原理。请先去了解一下。
👉 isa结构
👉 类的原理

如果你准备好了,我们就开始吧~

前期准备

main.m文件中加入测试代码

  • HTTeacher继承自HTPersonHTPerson继承自NSObject
  • teacherHTTeacher实例化对象
@interface HTPerson : NSObject
@end

@implementation HTPerson
@end

@interface HTTeacher: HTPerson
@end

@implementation HTTeacher
@end

int main(int argc, const char * argv[]) {
    
    @autoreleasepool {
        
        HTTeacher * teacher = [[HTTeacher alloc]init];

        NSLog(@"%p", teacher);
    }
    return 0;
}

NSLog位置加入断点

objc4 源码

objc4 源码下载-> objc4-781.tar.gz

objc_object

obj4源码中搜索struct objc_object:

image.png

这是对象在底层的实现模板。首元素是isa(这里涉及到struct结构的内存优化,我们这里记住结论。isaobjc_object的首位元素即可)

相关知识: 内存优化

objc_class

obj4源码中搜索struct objc_class:

image.png

从上图知道,在类的内存中,首地址表示isasuperclassisa后面,需要内存地址偏移8位获取。

梳理逻辑

image.png

探索路径:

1. 从对象开始探索

teacher对象

  • 打印地址:p/x teacher
  • 获取isa指针: x/g $0
  • 从isa指针中取出类地址: p/x 0x001d8001000021c9 >> 3 << 20 >> 17
  • 打印类: po 0x00000001000021c8
image.png

成功找到继承类HTTeacher

2 寻找父类源头:

查看上面准备的objc_class结构,父类首地址是isa指针,占用了8字节。

  • 所以我们从类地址偏移8位就可以找到superclass类。
  • 找到superclass地址: p/x 0x00000001000021c8 + 8
  • 获取父类的isa指针: x/g 0x00000001000021d0
  • 从isa指针中取出类地址: p/x 0x0000000100002178 >> 3 << 20 >> 17
  • 打印父类: po 0x0000000100002178
image.png

成功找到HTTeacher的父类HTPerson

为了一探究竟。我们一口气追根溯源,往上层层找寻父类
  • 寻找superclass地址:p/x 0x0000000100002178 + 8
  • 获取父类的isa指针: x/g 0x0000000100002180
  • 从isa指针中取出类地址: p/x 0x0000000100333140 >> 3 << 20 >> 17
  • 打印父类:po 0x0000000100333140
image.png

成功找到HTPerson的父类NSObject

再接再厉,往上溯源
  • 寻找superclass地址: p/x 0x0000000100333140 + 8
  • 获取父类的isa指针: x/g 0x0000000100333148
  • 从isa指针中取出类地址: p/x 0x0000000000000000 >> 3 << 20 >> 17
  • 打印父类:po 0x0000000000000000
image.png

NSObjet 的父类是nil(0x0000000000000000)。 到达尽头!

所以我们说OC中,想要确定类的继承关系,找到NSObject就可以停止了。因为已经到尽头了!

附上完整截图:


类的继承

3. 寻找isa的源头:

isa相比于类而言,不需要进行偏移。但是需要准确找到类中isa的地址

查看上面准备的objc_class结构,父类首地址是isa指针。

  • 我们应该用x/g打印获取isa的准确内存位置
  • 从isa中获取类的地址,我们需要准确截取shiftcls部分。
    (我一般使用 内存地址>>3 << 20 >> 17, 你们也可以&与上ISA_MASK 0x00007ffffffffff8ULL
  • 获取类的isa指针 x/g 0x00000001000021c8
  • 从Isa指针中取出类地址: p/x 0x00000001000021a0 >> 3 << 20 >> 17
  • 打印类名: po 0x00000001000021a0
image.png

成功找到HTTeacher元类

  • HTTeacher类地址是:0x00000001000021c8
  • HTTeacher元类地址是:0x00000001000021a0

我们接着往下。打印过程都一样。这里直接上完整打印图:

isa指向图

我们发现2个情况:

  1. HTTeacher的isa首先指向HTTeacher的元类,之后直接指向了NSObject元类。与HTTeacher的父类HTPerson完全无关
  2. NSObject元类的isa指针指向的是NSObject元类

1. 如何确定是NSObject元类,而不是NSObjet自身类?

image.png

我们打印NSObject自身类NSObject元类地址

  • 与上面地址0x00000001003330f0进行对比。 可以肯定上面打印的是NSObject元类地址

2. NSObject元类也是类,那它有父类(superclass)吗?

image.png

  • 通过指针偏移8位,到达superclass地址。
  • 打印发现NSObject元类有父类,它的父类指向了NSObject本类

3. NSObject元类有父类, 那其他元类(比如HTTeacher元类)有父类吗?

image.png

曾经的我以为打印不出来,那就是其他元类都没有父类咯?

聪明的你看出错误了吗😂

image.png

总结:

    1. 对象内的isa指针指向自己的类.
    1. 有完整的继承关系(每个类都通过superclass记录自己的父类,层层溯源)
    1. 根类NSObject
      NSObject的父类为nil,所以NSObject无父类
      所有类的最终父类都是NSObject
    1. isa的指向与类的继承无关
    1. 任何类isa都是先指向自己元类,再指向NSObject元类
      (除了NSObject类, 因为他自己元类就是NSObject元类)
    1. 根元类NSObject元类
      NSObject元类isa指向永远都是自己
    1. 元类也有父类,根元类(NSObject元类)的父类(superclass)是NSObject类

奉上经典的isa指向类的继承关系图

isa和类继承流程图.png

再奉上我的备注图:


isa和类继承流程图.png

欢迎一起交流学习。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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