iOS 中 weak 属性的实现机理详解

0 下载量 42 浏览量 更新于2024-08-28 收藏 156KB PDF 举报
iOS 中 weak 的实现代码示例 weak 属性关键字是 iOS 中一个非常重要的概念,它不会增加引用计数,但却能保证指针的安全访问,在对象释放后置为 nil,从而避免错误的内存访问。主要为了解决循环引用的问题。 在 objc 库中的 NSObject.mm、objc-weak.h 以及 objc-weak.mm 文件中,我们可以找到 weak 的实现过程。weak 的内部结构是由 Runtime 维护的, weak 表是一个hash表,key 是所指对象的指针,value 是 weak 指针的地址(这个地址的值是所指向对象的地址)数组。 weak 表是由单个自旋锁管理的散列表,用于存储指向某个对象的所有weak指针。SideTable 结构体用来管理引用计数表和weak表,并使用spinlock_lock自旋锁来防止操作表结构时可能的竞态条件。它用一个 64*128 大小的 uint8_t 静态数组作为 buffer 来保存所有的 SideTable 实例。 SideTable 结构体里面包含三个变量,第一个 spinlock_t,它是一个自旋锁,用来保证线程安全。第二个 RefcountMap,是引用计数表,每个对象的引用计数保存在全局的引用计数表中,一个对象地址对应一个引用计数。第三个就是 weak 表,所有的 weak 变量会被加入到全局的 weak 表中,表的 key 是 weak 修饰的变量指向的对象,value 值就是 weak 修饰的变量。 weak_table_t 结构体是 weak 表的具体实现,里面包含三个变量,第一个 weak_entry_t* weak_entries,用于保存所有指向指定对象的 weak 指针。第二个 size_t num_entries,用于存储空间,即 entries 的数目。第三个 uintptr_t mask,用于参与判断引用计数辅助量。第四个 uintptr_t max_hash_displacement,用于 hashkey 最大偏移量。 在 weak 表中,每个对象的 weak 指针都被保存在 weak_entry_t 结构体中,里面包含三个变量,第一个 uintptr_t location,用于存储 weak 指针的地址。第二个 uintptr_t value,用于存储 weak 指针的值。第三个 uintptr_t hash,用于存储 weak 指针的 hash 值。 weak 表的实现过程可以分为三个步骤:首先,创建 weak 表的实例,并将其加入到全局的 weak 表中。其次,weak 表中每个对象的 weak 指针都被保存在 weak_entry_t 结构体中。最后,weak 表使用 hash 函数来快速查找 weak 指针。 在使用 weak 属性关键字时,需要注意 weak 指针的生命周期。在对象释放后,weak 指针会被置为 nil,从而避免错误的内存访问。但是,weak 指针的生命周期是由 Runtime 维护的,开发者无需手动管理 weak 指针的生命周期。 weak 属性关键字是 iOS 中一个非常重要的概念,它能够保证指针的安全访问,并避免错误的内存访问。但是,weak 指针的生命周期是由 Runtime 维护的,开发者需要了解 weak 的实现过程,以便更好地使用 weak 属性关键字。