iOS经典面试题之深入解析runtime是如何实现weak变量的自动置nil

一、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 底层调用流程

在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

╰つ栺尖篴夢ゞ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值