七、weak置空原理
当面试官问你weak置空原理是什么,你可能只知道weak怎么用却不知道怎么答吧
在weak
一行打下断点运行项目
int main(int argc, const char * argv[]) {
@autoreleasepool {
FXPerson *person = [[FXPerson alloc] init];
id __weak person = object;
}
return 0;
}
Xcode菜单栏Debug->Debug Workflow->Always show Disassembly
打上勾查看汇编——汇编代码会来到libobjc库
的objc_initWeak
1.weak创建过程
①objc_initWeak
-
location
:表示__weak指针
的地址(我们研究的就是__weak指针
指向的内容怎么置为nil) -
newObj
:所引用的对象,即例子中的person
id
objc_initWeak(id *location, id newObj)
{
if (!newObj) {
*location = nil;
return nil;
}
return storeWeak<DontHaveOld, DoHaveNew, DoCrashIfDeallocating>
(location, (objc_object*)newObj);
}
②storeWeak
-
HaveOld
:weak指针之前是否已经指向了一个弱引用 -
HaveNew
:weak指针是否需要指向一个新引用 -
CrashIfDeallocating
:如果被弱引用的对象正在析构,此时再弱引用该对象,是否应该crash
storeWeak最主要的两个逻辑点(源码太长,这里不贴了)
由于是第一次调用,所以走
haveNew
分支——获取到的是新的散列表SideTable,主要执行了weak_register_no_lock方法来进行插入
③weak_register_no_lock
- 主要进行了
isTaggedPointer
和deallocating
条件判断 - 将被弱引用对象所在的
weak_table
中的weak_entry_t
哈希数组中取出对应的weak_entry_t
- 如果
weak_entry_t
不存在,则会新建一个并插入 - 如果存在就将指向被弱引用对象地址的指针
referrer
通过函数append_referrer
插入到对应的weak_entry_t
引用数组
④append_referrer
找到弱引用对象的对应的weak_entry
哈希数组中插入
2.weak创建流程
3.weak销毁过程
由于弱引用在析构dealloc时自动置空,所以查看dealloc的底层实现并LLVM调试
-
_objc_rootDealloc
->rootDealloc
-
rootDealloc
->object_dispose
-
object_dispose
->objc_destructInstance
-
objc_destructInstance
->clearDeallocating
-
clearDeallocating
->sidetable_clearDeallocating
-
sidetable_clearDeallocating3
->table.refcnts.erase(it)
4.weak销毁流程
(非本人做图)具体可查阅iOS底层学习 - 内存管理之weak原理探究