iOS的weak实现原理基于Objective-C运行时和SideTable机制,核心是通过弱引用表(weak_table_t)和引用计数表(SideTable)协同管理对象生命周期。以下是关键细节:
一、底层数据结构
SideTable:每个对象关联一个SideTable,包含:
spinlock_t(自旋锁):保证线程安全。RefcountMap(引用计数表):存储对象的引用计数。weak_table_t(弱引用表):存储所有指向该对象的weak指针。
weak_table_t:全局哈希表,以对象地址为key,存储所有指向该对象的弱引用指针地址数组(value)。
1
2
3
4
5
6struct weak_table_t {
weak_entry_t *weak_entries; // 动态数组,存储弱引用条目
size_t num_entries; // 当前条目数
uintptr_t mask; // 哈希表容量掩码
uintptr_t max_hash_displacement; // 最大哈希冲突步长
};weak_entry_t:哈希表的条目,记录对象地址(referent)和弱引用指针集合(referrers),采用共用体优化内存占用。
二、weak指针的工作流程
初始化
- 当声明
__weak id obj = strongObj时,编译器调用objc_initWeak函数,。 - 运行时将
weak指针地址(&obj)和对象地址(strongObj)注册到弱引用表中。
- 当声明
存储方式
- 弱引用表使用对象的地址作为键,通过哈希表快速定位到对应的
weak_entry_t。 weak_entry_t内部存储所有指向该对象的weak指针地址(数组或链表结构)。- 通过自旋锁保证多线程环境下弱引用表的操作安全性。
- 弱引用表使用对象的地址作为键,通过哈希表快速定位到对应的
对象释放时
- 当对象的引用计数为0时,
dealloc方法会调用weak_clear_no_lock。 - 遍历弱引用表中所有指向该对象的
weak指针,将其置为nil(防止悬垂指针)。 - 清理完成后,从weak表中删除对应的
weak_entry_t条目。
- 当对象的引用计数为0时,
三、自动置nil机制
- 触发时机:对象被释放时,通过objc_destructInstance触发弱引用清理。
- 线程安全:通过SideTable的自旋锁保证多线程下弱引用表的操作安全。
- 性能优化:弱引用表使用开放寻址法解决哈希冲突,减少内存碎片。
四、与unsafe_unretained的区别
| 特性 | weak | unsafe_unretained |
|---|---|---|
| 自动置nil | 是 | 否 |
| 安全性 | 高(避免野指针) | 低(可能访问已释放对象) |
| 性能开销 | 有(维护weak表) | 无 |
| 使用场景 | 循环引用解决 | 性能敏感且能确保对象生命周期的场景 |
| 兼容性 | 仅ARC环境 | ARC/MRC均可 |
五、性能优化建议
- 避免过度使用weak:每个weak引用都需要维护全局weak表,频繁操作会影响性能。
- 优先使用strong:在明确知道不会造成循环引用的场景使用strong引用。
- 局部weak变量:方法内部的weak变量在作用域结束后会自动清理,比属性更高效。
- 注意线程安全:weak操作不是完全线程安全的,多线程环境需谨慎。
六、典型应用场景
- Delegate模式:防止相互强引用导致的内存泄漏。
- Block捕获:通过
__weak typeof(self)配合__strong临时强引用,避免block执行期间对象意外释放。 - NSTimer目标对象:解决timer与目标对象间的循环引用。
- 父子对象关系:子对象对父对象的引用通常应为weak。
weak的实现本质是通过全局弱引用表动态跟踪对象状态,结合SideTable的线程安全机制和哈希表高效查找,实现了安全、自动化的弱引用管理。这一设计平衡了内存安全与运行时性能。
引用链接:
[1] iOS之深入解析weak关键字的底层原理 - CSDN下载
[2] 「iOS」————weak底层原理 - CSDN博客
[3] iOS——weak实现原理 - CSDN博客
[4] iOS weak的实现原理 - www.cloud.tencent.com
[5] [iOS] weak关键字的实现原理 - CSDN博客
[6] 深入解析Objective-C中的weak引用实现原理,-CSDN博客 - CSDN博客
[7] [OC学习笔记]weak的实现原理 - CSDN博客
[8] 理解Objective-C 弱引用与内存管理 - CSDN博客
[9] iOS开发进阶(十六): Objective-C block、weakself、strongself_data - CSDN博客
[10] 浅析objective-c中的strong和weak - CSDN博客
[11] weak的底层原理 - CSDN博客
[12] 揭开iOS 中 weak 指针的神秘面纱:从原理到实践 - 掘金开发者社区
[13] [iOS开发] ——weak底层原理 - CSDN博客
[14] 老生常谈的iOS- weak原理,你真的懂得还是为了应付面试 - 博客园
[15] [iOS]-weak底层原理(sidetable相关,附带引用计数原理) - CSDN博客
[16] [iOS] —— 属性关键字及weak关键字底层原理_ios weak-CSDN博客 - CSDN博客
[17] iOS_Runtime是什么?原理?作用?怎么实现weak?使用 - 腾讯云
[18] iOS中Objective-C&Swift知识点梳理 - Jonathan
[19] Tip4 - 关于 Weak 应该知道的 - 掘金开发者社区
[20] iOS weak的实现原理详解 - 简书 - 简书社区
[21] iOS weak实现原理和销毁过程 - 简书社区
[22] iOS内存管理08 – weak的底层实现原理 - 简书 - 简书社区
[23] iOS weak 底层实现原理 - luowei.github.io
[24] iOS weak 底层实现原理(二):objc-weak 函数列表全解析_牛客网 - 牛客网
[25] [iOS分类、关联对象]如何使用关联对象给分类实现一个weak的属性 - CSDN博客
[26] iOS弱引用 - CSDN博客