• weak的实现原理


             iOS 在运行时维护着一个全局的弱引用表,该表是一个 hash 表,hash表的 key 是 对象本身,value 是指向该对象的所有 weak 指针的地址数组。   
    1. /**
    2. 全局的弱引用表,本质是一个hash结构,对象本身作为key,
    3. 存储weak修饰的指针地址的weak_entry_t作为value
    4. */
    5. struct weak_table_t {
    6. // 保存了所有指向特地对象的 weak指针集合
    7. weak_entry_t *weak_entries;
    8. // hash数组中元素个数
    9. size_t num_entries;
    10. // hash数组的长度,而不是元素个数。比如,数组长度可能是64,而元素个数仅存了2个
    11. uintptr_t mask;
    12. // hash冲突最大次数, hash数组采用开放定址法解决hash冲突
    13. uintptr_t max_hash_displacement;
    14. };
            以下述代码为例:
    1. NSObject * obj = [[NSObject alloc] init];
    2. __weak NSObject *p1 = obj;
    3. __weak NSObject *p2 = obj;
    4. NSObject ** referrer1 = &p1;
    5. NSObject ** referrer2 = &p2;
    6. [obj release];

             hash表的key为obj,hash表的值weak_entries的referers属性被赋值为[referrer1, referrer2];

            当weak修饰的对象obj被销毁时,iOS在运行时会从哈希表中查找到所有指向此对象的 weak 指针,并将其全部置为空 nil,即通过执行*referrer1 = NULL和*referrer2 = NULL,实现将p1和p2置为NULL。
     
    1. weak_clear_no_lock(weak_table_t *weak_table, id referent_id) {
    2. // 在weak_table中对应的weak_entry_t
    3. objc_object *referent = (objc_object *)referent_id;
    4. weak_entry_t *entry = weak_entry_for_referent(weak_table, referent);
    5. weak_referrer_t referrers = entry->referrers;
    6. int count = TABLE_SIZE(entry);
    7. for (size_t i = 0; i < count; ++i) {
    8. objc_object **referrer = referrers[i];
    9. if (referrer) {
    10. // 如果weak指针确实弱引用了对象 referent,则将weak指针设置为nil
    11. if (*referrer == referent) {
    12. *referrer = nil;
    13. }
    14. }
    15. }
    16. }

            iOS在ARC下通过引入weak标识, 大大减少了以前retain或assign标识的对象在被销毁后可能出现野指针的情况,进而有效提升了代码健壮性。

  • 相关阅读:
    产品经理是干什么的?产品经理的工作内容与职责
    写给前端的 react-native 入门指南
    Golang如何使用命令行-- flag库
    7zip自带hash校验功能
    Linux系统中如何开启和配置OpenGauss数据库的远程连接
    四、分类算法 - 朴素贝叶斯算法
    开发必备的常用 Linux 命令整理
    element 表格多级表头子列固定
    【Minecraft开服教学】使用 MCSM 面板一键搭建我的世界服务器 并使用内网穿透公网远程联机
    牛客网刷题——JAVA
  • 原文地址:https://blog.csdn.net/holyli1134516796/article/details/136377180