深入解析Halfrost-Field项目中ObjC对象的生命周期

深入解析Halfrost-Field项目中ObjC对象的生命周期

Halfrost-Field ✍🏻 这里是写博客的地方 —— Halfrost-Field 冰霜之地 Halfrost-Field 项目地址: https://gitcode.com/gh_mirrors/ha/Halfrost-Field

前言

在面向对象编程的世界里,对象就像一个个有生命的个体,它们从诞生到消亡,经历着完整的生命周期。本文将深入探讨Halfrost-Field项目中关于Objective-C对象生命周期的精彩内容,带你全面了解对象从创建到销毁的每一个关键环节。

一、对象的孕育:alloc过程解析

1. alloc方法的调用链

当我们调用[MyClass alloc]时,实际上触发了一系列关键方法调用:

+ (id)alloc {
    return _objc_rootAlloc(self);
}

id _objc_rootAlloc(Class cls) {
    return callAlloc(cls, false, true);
}

2. 核心分配逻辑

callAlloc方法中,系统会根据不同情况选择最优的内存分配策略:

static ALWAYS_INLINE id callAlloc(Class cls, bool checkNil, bool allocWithZone) {
    // 检查是否有自定义的alloc/allocWithZone实现
    if (!cls->ISA()->hasCustomAWZ()) {
        // 快速分配路径
        if (cls->canAllocFast()) {
            bool dtor = cls->hasCxxDtor();
            id obj = (id)calloc(1, cls->bits.fastInstanceSize());
            obj->initInstanceIsa(cls, dtor);
            return obj;
        } else {
            // 常规分配路径
            return class_createInstance(cls, 0);
        }
    }
    // 使用自定义的allocWithZone
    return [cls allocWithZone:nil];
}

3. 内存分配的关键点

  • hasCustomAWZ:判断类是否有自定义的alloc/allocWithZone实现
  • canAllocFast:判断是否可以使用快速分配路径
  • fastInstanceSize:计算对象的实例大小
  • calloc:实际分配内存的函数,会自动将内存初始化为0

4. isa指针初始化

对象创建后,需要初始化其isa指针,这是对象与类关联的关键:

inline void objc_object::initIsa(Class cls, bool indexed, bool hasCxxDtor) {
    if (!indexed) {
        isa.cls = cls;
    } else {
        isa.bits = ISA_MAGIC_VALUE;
        isa.has_cxx_dtor = hasCxxDtor;
        isa.shiftcls = (uintptr_t)cls >> 3;
    }
}

二、对象的出生:init方法揭秘

1. init方法的本质

- (id)init {
    return _objc_rootInit(self);
}

id _objc_rootInit(id obj) {
    return obj;
}

可以看到,init方法实际上什么都没做,只是返回了对象本身。这是一个设计模式,允许子类重写init方法进行自定义初始化。

2. 为什么需要init方法

虽然alloc已经完成了内存分配和基本初始化,但init方法提供了以下好处:

  • 允许子类进行自定义初始化
  • 提供统一的初始化接口
  • 可以返回不同的实例(如单例模式)

三、对象的成长:内存结构与消息机制

1. 对象的内存布局

一个Objective-C对象在内存中主要包含:

  • isa指针:指向对象的类
  • 实例变量:存储对象的具体数据

2. 类与元类的关系

每个类都有一个对应的元类(meta-class),它们的关系如下:

  • 实例对象的isa指向类
  • 类的isa指向元类
  • 元类的isa指向根元类
  • 根元类的isa指向自己

3. 方法存储的位置

  • 实例方法(-方法)存储在类中
  • 类方法(+方法)存储在元类中
  • NSObject的特殊处理:根元类中会实现NSObject协议的类方法

4. 属性访问的本质

属性访问实际上是基于对象地址的偏移量计算:

// 伪代码表示属性访问
void *propertyAddress = objectAddress + offset;

四、对象的销毁:dealloc过程详解

1. dealloc调用链

- (void)dealloc {
    _objc_rootDealloc(self);
}

void _objc_rootDealloc(id obj) {
    obj->rootDealloc();
}

2. 销毁条件判断

rootDealloc中,系统会检查多种条件来决定如何释放对象:

inline void objc_object::rootDealloc() {
    if (isTaggedPointer()) return;
    
    if (isa.indexed && 
        !isa.weakly_referenced && 
        !isa.has_assoc && 
        !isa.has_cxx_dtor && 
        !isa.has_sidetable_rc) {
        // 简单情况直接释放
        free(this);
    } else {
        // 复杂情况需要特殊处理
        object_dispose((id)this);
    }
}

3. 复杂对象的销毁

对于有附加属性的对象,销毁过程更复杂:

id object_dispose(id obj) {
    objc_destructInstance(obj);
    free(obj);
    return nil;
}

void *objc_destructInstance(id obj) {
    if (obj->hasCxxDtor()) {
        object_cxxDestruct(obj);
    }
    if (obj->hasAssociatedObjects()) {
        _object_remove_assocations(obj);
    }
    obj->clearDeallocating();
    return obj;
}

五、总结:对象生命周期全景图

  1. 孕育阶段:通过alloc方法分配内存,初始化isa指针
  2. 出生阶段:通过init方法完成初始化(可自定义)
  3. 成长阶段:通过isa指针查找方法,通过地址偏移访问属性
  4. 销毁阶段:释放关联对象、调用析构函数,最终释放内存

理解Objective-C对象的完整生命周期,对于编写高效、稳定的iOS/macOS应用至关重要。希望本文能帮助你深入理解对象从生到死的每一个细节。

Halfrost-Field ✍🏻 这里是写博客的地方 —— Halfrost-Field 冰霜之地 Halfrost-Field 项目地址: https://gitcode.com/gh_mirrors/ha/Halfrost-Field

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宋韵庚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值