一、weak 基本用法
weak 是弱引用,用 weak 来修饰、描述所引用对象的计数器并不会增加,而且 weak 会在引用对象被释放的时候自动置为 nil,这也就避免了野指针访问坏内存而引起奔溃的情况,另外 weak 也可以解决循环引用。
拓展:为什么修饰代理使用 weak 而不是用 assign?
assign 可用来修饰基本数据类型,也可修饰 OC 的对象,但如果用 assign 修饰对象类型指向的是一个强指针,当指向的这个指针释放之后,它仍指向这块内存,必须要手动给置为 nil,否则会产生野指针,如果还通过此指针操作那块内存,会导致 EXC_BAD_ACCESS 错误,调用了已经被释放的内存空间;而 weak 只能用来修饰 OC 对象,而且相比 assign 比较安全,如果指向的对象消失了,那么它会自动置为 nil,不会导致野指针。
二、weak 原理概括
weak 表其实是一个哈希表,key 是所指对象的指针,value 是 weak 指针的地址数组。(value 是数组的原因是:因为一个对象可能被多个弱引用指针指向)
Runtime 维护了一张 weak 表,用来存储某个对象的所有的 weak 指针。
weak 原理实现过程三步骤
Runtime会维护一个weak表,用于维护指向对象的所有weak指针。weak表是一个哈希表,其key为所指对象的指针,value为weak指针的地址数组。
具体过程如下:
1、初始化时:runtime会调用objc_initWeak函数,初始化一个新的weak指针指向对象的地址。
2、添加引用时:objc_initWeak函数会调用 objc_storeWeak() 函数,更新指针指向,创建对应的弱引用表。
3、释放时,调用clearDeallocating函数。clearDeallocating函数首先根据对象地址获取所有weak指针地址的数组,然后遍历这个数组把其中的数据设为nil,最后把这个entry从weak表中删除,最后清理对象的记录。