iOS经典面试题之“runtime是如何实现weak变量的自动置nil”
【摘要】
一、weak 属性特点
weak 表明该属性定义了一种“非拥有关系” (nonowning relationship);为 weak 属性设置新值时,设置方法既不保留新值,也不释放旧值;同 assign...
一、weak 属性特点
- weak 表明该属性定义了一种“非拥有关系” (nonowning relationship);
- 为 weak 属性设置新值时,设置方法既不保留新值,也不释放旧值;
- 同 assign 类似,然而在属性所指的对象释放时候,属性值也会清空(nil out)。
二、runtime 如何实现 weak 属性
① 实现步骤
- 初始化时:runtime 会调用 objc_initWeak 函数,初始化一个新的 weak 指针指向对象的地址。
- 添加引用时:objc_initWeak 函数会调用 objc_storeWeak(&weakPo, Model) 函数。
- 释放时:调用 clearDeallocating 函数,clearDeallocating 函数首先根据对象地址获取所有 weak 指针地址的数组,然后遍历这个数组把其中的数据设为 nil,最后把这个 entry 从 weak 表中删除,最后清理对象的记录。
② objc_storeWeak(&weakPo, Model) 作用
- objc_storeWeak(&weakPo, Model) 的作用是更新指针指向(指针可能原来指向着其他对象,这时候需要将该 weak 指针与旧对象解除绑定,会调用到 weak_unregister_no_lock),如果指针指向的新对象非空,则创建对应的弱引用表,将 weak 指针与新对象进行绑定(即把赋值对象(Model)的内存地址作为键值key,将weak修饰的属性变量(weakPo)的内存地址(& weakPo)作为value),会调用到weak_register_no_lock,注册到 weak 表中。在这个过程中,为了防止多线程中竞争冲突,会有一些锁的操作。
- 如果Model 为0(nil),那么把变量 weakPo 的内存地址 &weakPo 从 weak 表中删除,可以把 objc_storeWeak(&weakPo, Model) 理解为:objc_storeWeak(value, key),并且当key变nil,将value置nil。
- 在 Model 非 nil 时,weakPo 和 Model 指向同一个内存地址,在 Model 变 nil 时,weakPo 变 nil。此时向 weakPo 发送消息不会崩溃:在 Objective-C 中向 nil 发送消息是安全的。
三、runtime 是如何实现 weak 变量的自动置 nil ?
- runtime 对注册的类,会进行内存布局,从一个粗粒度的概念上来讲,这时候 weak 对象会放入一个 hash 表中,这是一个全局表,表中是用 weak 指向的对象内存地址作为 key,用所有指向该对象的 weak 指针表作为 value。
- 当此对象的引用计数为 0 的时候会 dealloc,假如该对象内存地址是 address,那么就会以 address 为 key,在这个weak 表中搜索,找到所有以 address 为键的 weak 对象,从而设置为 nil。
- 简而言之,对象释放的时候 - dealloc: 步骤如下:
- C++函数释放: object_ cxxDestruct;
- 移除关联属性:_ object_ remove_ assocations;
- 将弱引用自动设置nil : weak_ clear_ no_ lock(&table.weak_ table, (id)this);
- 引用计数处理: table.refcnts.erase(this);
- 销毁对象: free(obj);
四、weak 底层调用流程
文章来源: blog.csdn.net,作者:Serendipity·y,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/Forever_wj/article/details/115034919
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)