__weak修饰符,是我们经常用来解决循环引用的良药利器,它展现出如此强大的魔力,我却一无所知。所以我决定去看一看它的实现。
在看了《Objective-C高级编程》一书以后,关于__weak的实现理念,我用简单的方式概括一下为:
id obj = 1;
id __weak obj1 = obj;
/*编译器模拟代码*/
id obj1;
obj1 = 0;
objc_storeWeak(&obj1,obj);
objc_storeWeak(&obj1,0);
关于objc_storeWeak的底层实现呢,下次再看。
底层实现理念为将obj的地址作为键值,然后将__weak修饰符修饰的obj1的地址注册到weak表中。
可以简单的看作是{&obj:&obj1},便于理解。
如果第二个参数是0,则把变量的地址从weak表中删除。
由于一个对象可以同时同时赋值给多个__weak修饰符的变量中,所以对于一个键值,可注册多个变量的地址。
__weak修饰符所修饰的变量地址作为键值是注册到一个weak表中的,
这里为了便于理解,可以简单的看作是{&obj:@[&obj1,&obj2,&obj3......]}。
释放对象时,程序的动作运行:
1.先调用objc_release
2.因为引用计数为0所以执行dealloc
3._objc_rootDealloc
4.object_dispose
5.objc_destructInstance
6.objc_clear_deallocating
当obj将要被被废弃的时候,会通过obj的地址在weak表找寻到所对应的所有__weak修饰符变量的地址,赋值为nil,然后将记录删除,再从引用计数表中删除废弃对象的地址为键值的记录。
但是由此可知,如果大量的使用附有__weak修饰符的变量,则会消耗相应的CPU资源,所以良策是只在需要避免循环引用时使用__weak修饰符。