返回

揭秘底层 weak 的实现原理——深入剖析 objc_initWeak

IOS

引言

在 Objective-C 中,weak 修饰符用于表示对对象的弱引用,这是一种不影响对象生命周期的引用方式。与强引用不同,weak 引用不会阻止对象被释放,从而避免了循环引用的可能性。

objc_initWeak

objc_initWeak 是 weak 机制的核心函数。它负责初始化一个 SideTable 结构,用于管理弱引用。SideTable 是一个哈希表,其中键是对象的地址,值是一个指向该对象弱引用的指针。

当我们创建一个 weak 引用时,objc_initWeak 会执行以下步骤:

  1. 创建一个 SideTable,如果还没有的话。
  2. 在 SideTable 中查找对象的地址。
  3. 如果对象不存在,则将一个 weak 指针添加到 SideTable 中,并将其设置为 nil。
  4. 返回 weak 指针。

storeWeak

storeWeak 函数用于将对象存储到 weak 引用中。它执行以下步骤:

  1. 调用 objc_initWeak 获取弱指针。
  2. 将对象分配给 weak 指针。

SideTable

SideTable 是一个哈希表,用于管理弱引用。它包含以下字段:

  • table: 一个哈希表,其中键是对象的地址,值是 weak 指针。
  • count: 哈希表中的条目数。
  • freeList: 一个 free list,用于存储已释放 weak 指针的地址。
  • lock: 一个互斥锁,用于同步对 SideTable 的访问。

实现细节

weak 实现的更详细细节涉及以下内容:

  • 哈希冲突处理: 当两个对象映射到同一哈希桶时,SideTable 使用链表来解决冲突。
  • 弱指针的生命周期: weak 指针的生存期与 SideTable 的生存期相同。当 SideTable 被释放时,所有 weak 指针也将被释放。
  • 内存管理: SideTable 和 weak 指针都在运行时进行管理,不需要显式释放。

使用 weak 的注意事项

使用 weak 时,需要考虑以下注意事项:

  • 避免循环引用: weak 引用可以防止循环引用,但不能防止对象图中其他类型的引用循环。
  • 对象生命周期: 弱引用不影响对象的释放,因此在使用 weak 引用时,必须意识到对象的生命周期。
  • 并发安全性: SideTable 是线程安全的,但访问 weak 引用本身不是线程安全的。

结论

weak 是 Objective-C 中一种强大的工具,用于管理引用和防止循环引用。通过理解其底层实现原理,我们可以更好地利用 weak,优化代码并提高内存效率。