魏名华

不要偷懒,做更好的自己

Nothing


No Welcome Message

手写Weak

【从历年weak看iOS面试】 2013年 面试官:代理用weak还是strong? 我 :weak 。 面试官:明天来上班吧

2014年 面试官:代理为什么用weak不用strong? 我 : 用strong会造成循环引用。 面试官:明天来上班吧

2015年 面试官:weak是怎么实现的? 我 :weak其实是 系统通过一个hash表来实现对象的弱引用 面试官:明天来上班吧

2016年 面试官:weak是怎么实现的? 我 :runtime维护了一个weak表,用于存储指向某个对象的所有weak指针。weak表其实是一个hash(哈希)表,key是所指对象的地址,Value是weak指针的地址(这个地址的值是所指对象指针的地址)数组。 面试官:明天来上班吧

2017年 面试官:weak是怎么实现的? 我 : 1 初始化时:runtime会调用objc_initWeak函数,初始化一个新的weak指针指向对象的地址。 2 添加引用时:objc_initWeak函数会调用 storeWeak() 函数, storeWeak() 的作用是更新指针指向,创建对应的弱引用表。 3 释放时,调用clearDeallocating函数。clearDeallocating函数首先根据对象地址获取所有weak指针地址的数组,然后遍历这个数组把其中的数据设为nil,最后把这个entry从weak表中删除,最后清理对象的记录。 面试官:明天来上班吧

2018年 面试官:weak是怎么实现的? 我 :跟2017年说的一样,还详细补充了objc_initWeak, storeWeak, clearDeallocating的实现细节。 面试官:小伙子基础不错。13k ,996干不干?干就明天来上班。。 下一个

2019年 面试官:weak是怎么实现的? 我 : 别说了,拿纸来,我动手实现一个。 面试官:等写完后,面试官慢悠悠的说,小伙子不错,我考虑考虑,你先回去吧

@onevcat:可以加一问 Swift 的 weak 和 ObjC 的 weak 实现有何异同什么的 [笑cry]

2020年: 我觉得苹果的实现不好,这是我的优化方案…

iOS 底层解析weak的实现原理(包含weak对象的初始化,引用,释放的分析)https://www.jianshu.com/p/13c4fb1cedea

实现主要在 objc-weak.h、objc-weak.mm 和 NSObject.mm 这三个文件中。

  1. 初始化时:runtime会调用objc_initWeak函数,初始化一个新的weak指针指向对象的地址。

当我们像下面那样初始化一个弱引用时:

// NSObject *o = ...;
__weak id weakPtr = o;

/////编译器会转换为下面的实现:

// NSObject *o = ...;
objc_initWeak(&weakPtr, o);
  1. 添加引用时:objc_initWeak函数会调用 storeWeak() 函数, storeWeak() 的作用是更新指针指向,创建对应的弱引用表。

  2. 释放时,调用clearDeallocating函数。clearDeallocating函数首先根据对象地址获取所有weak指针地址的数组,然后遍历这个数组把其中的数据设为nil,最后把这个entry从weak表中删除,最后清理对象的记录。

swift中的unowned

unowned使用在Swift中,也会分 weak 和 unowned。unowned 的含义跟 __unsafe_unretained 差不多。假如很明确的知道对象的生命期,也可以选择 unowned。

Swift 的 weak 和 ObjC 的 weak 实现有何异同 https://juejin.im/entry/5a5f2f646fb9a01c9950d7f4

swift4之前

在 Swift 里苹果把弱引用的实现简化了,弱引用变量只保存指向目标对象的地址,并通过对象內的弱引用计数进行内存管理。 Swift 把对象的析构和释放时机进行了解耦,析构发生在强引用数为零时,只有强弱引用数都为零才会释放。 使用弱引用时,runtime 会检查目标对象的状态,如果已经析构了就会执行 zeroing 操作。

swift4之后

苹果再次加入 SideTable 的机制。

不过此 SideTable 跟 OC 的 SideTable 不一样,系统不再是把它作为全局对象使用。新的 SideTable 是针对有需要的对象而创建,系统会为目标对象分配一块新的内存来保存该对象额外的信息。