1.runtime中如何实现weak
-
生成weak对象
{
//obj是__strong修饰且被赋值的对象
id __weak obj1 = obj;
}
//编译器的模拟代码
//转化1
id obj1;
objc_initWeak(&obj1, obj);
objc_destroyWeak(&obj1); //作用域结束,释放对象
//转化2
id obj1;
obj1 = 0;
objc_storeWeak(&obj1, obj);
objc_storeWeak(&obj1, 0);
weak对象有一张weak表(类似引用计数表),是作为散列表被实现。赋值对象(obj)的内存地址作为key,weak对象(obj1)的内存地址作为value存储。一个objc可以赋值给多个weak对象,所以一个key可以对应多个value。
-
释放weak对象
(1) objc_release
(2) 引用计数为0,执行dealloc
(3) _objc_rootDealloc
(4) object_dispose
(5) objc_destructInstance
(6) objc_clear_deallocating
主要讲一下第(6)步,它做的事情有:
1)从weak表中获取weak对象的地址为键值的记录
2)将包含在记录中所有附有__weak修饰符变量的地址,赋值为nil
3)从weak表中删除该记录
4)从引用计数表中删除weak对象的地址为键值的记录
2.__weak对象与autoreleasepool的关系
__weak修饰符的变量,会注册到autoreleasepool中
{
//obj是__strong修饰且被赋值的对象
id __weak obj1 = obj;
NSLog(@"%@", obj1);
}
//编译器的模拟代码
id obj1;
objc_initWeak(&obj1, obj);
id tmp = objc_loadWeakRetained(&obj1);
objc_autorelease(tmp);
NSLog(@"%@", obj1);
objc_destroyWeak(&obj1); //作用域结束,释放对象
objc_loadWeakRetained函数取出附有__weak修饰符变量所引用的对象,并retain
objc_autorelease函数将对象注册到autoreleasepool中
所以,如果大量使用附有weak修饰符的变量,注册到autoreleasepool的对象也会大量增加。解决办法:最好先暂时将weak对象赋值给strong修饰符的变量后再使用