runtime
对注册的类会进行布局,
1.对于weak
修饰的对象会放入一个hash
表中;
2.用weak
指向的对象内存地址
作为key
;
3.当此对象的引用计数
为0的时候会dealloc
。
假如weak
指向的对象内存地址
是a,那么就会以a为键
在这个weak
表中搜索,找到所有以a为键
的weak
对象,从而设置为nil
。
weak
释放为nil
过程
weak
被释放为nil
,需要对对象整个释放过程了解,如下是对象释放的整体流程:
1、调用objc_release
2、因为对象的引用计数为0,所以执行dealloc
3、在dealloc
中,调用了_objc_rootDealloc
函数
4、在_objc_rootDealloc
中,调用了object_dispose
函数
5、调用objc_destructInstance
6、最后调用objc_clear_deallocating
。
对象准备释放时,调用clearDeallocating
函数。clearDeallocating
函数首先根据对象地址获取所有weak指针地址的数组
,然后遍历这个数组把其中的数据设为nil
,最后把这个entry
从weak
表中删除,最后清理对象的记录。
总结
weak
是Runtime
维护了一个hash(哈希)表
,用于存储指向某个对象的所有weak指针。weak
表其实是一个hash(哈希)表
,Key
是所指对象的地址
,Value是weak指针的地址(这个地址的值是所指对象指针的地址
)数组
。
1、初始化时:
runtime
会调用objc_initWeak
函数,初始化一个新的weak
指针 指向对象的地址。
2、添加引用时:
objc_initWeak
函数 会调用objc_storeWeak()
函数,objc_storeWeak()
的作用是更新指针指向,创建对应的弱引用表。
3、释放时,调用
clearDeallocating
函数。clearDeallocating
函数首先根据对象地址获取所有weak
指针地址的数组,然后遍历这个数组把其中的数据设为nil
,最后把这个entry
从weak
表中删除,最后清理对象的记录。
sideTable
struct SideTable {
// 保证原子操作的自旋锁
spinlock_t slock;
// 引用计数的 hash 表
RefcountMap refcnts;
// weak 引用全局 hash 表
weak_table_t weak_table;
}
struct weak_table_t {
// 保存了所有指向指定对象的 weak 指针
weak_entry_t *weak_entries;
// 存储空间
size_t num_entries;
// 参与判断引用计数辅助量
uintptr_t mask;
// hash key 最大偏移值
uintptr_t max_hash_displacement;
};
站在巨人的肩膀上学习!如有侵权,请联系删除
网友评论