引言:weak在日常开发中其实挺常用的,weak所修饰的变量,在其所引用的对象被废弃时,会将nil赋值给变量。由于上述作用,weak常常能解决循环引用等问题。
所以现在就来看看weak这个修饰符到底做了些什么
直接上代码
id __weak weakObj = Obj
编译器模拟:
id weakObj;
objc_initWeak(&weakObj, Obj);
objc_destoryWeak(&weakObj);
通过源码,可知objc_initWeak其实等用于,将变量赋初值0,并调用objc_storeWeak函数,而objc_destoryWeak将0作为参数调用objc_storeWeak,所以最上面的代码本质可以如下所示
id weakObj;
weaksobj = 0;
objc_storeWeak(&weakObj, obj);
objc_storeWeak(&weakObj, 0);
上述代码,objc_storeWeak
会将obj
(即引用对象)的地址作为key,weakObj
的地址作为值,存储到一个weak表,专门用来管理weak修饰的变量处理。而当参数为0的含义,就是在weak表中查询weakObj的地址的记录,并将其从表中删除。
注意:由于虽然obj
的地址作为key,但是由于一个引用对象可以赋值给多个weak修饰的变量,所以应该是一对多的关系,类似{obj地址:weakobj1地址,weakobj2地址, weakobj3地址...}
这种形式存在。
释放对象的时候程序动作:
- objc_release
- 因为计数器为0,会执行dealloc
- _objc_rootDealloc
- object_dispose
- objc_destructInstance
- objc_clear_deallocating
关键点就在objc_clear_deallocationg
其实本质操作:
- weak表中查询dealloc对象的地址的记录
- 将查询到的记录的weak修饰的是变量都赋值为nil
- 从weak表中将dealloc对象地址的记录删除
- 引用计数表中删除dealloc对象地址的记录
上述步骤就实现了weak修饰变量所引用的对象被废弃时,将nil赋值给该变量。