
屏幕快照 2018-11-17 下午11.00.18.png
objc_initweak() 函數(shù)具體實(shí)現(xiàn)是怎樣的?
添加weak 變量

屏幕快照 2018-11-17 下午11.02.11.png
id
objc_initWeak(id *location, id newObj)
{
if (!newObj) {
*location = nil;
return nil;
}
return storeWeak<false/*old*/, true/*new*/, true/*crash*/>
(location, (objc_object*)newObj);
}
template <bool HaveOld, bool HaveNew, bool CrashIfDeallocating>
static id
storeWeak(id *location, objc_object *newObj)
{
assert(HaveOld || HaveNew);
if (!HaveNew) assert(newObj == nil);
Class previouslyInitializedClass = nil;
id oldObj;
SideTable *oldTable;
SideTable *newTable;
// Acquire locks for old and new values.
// Order by lock address to prevent lock ordering problems.
// Retry if the old value changes underneath us.
retry:
if (HaveOld) {
oldObj = *location;
oldTable = &SideTables()[oldObj];
} else {
oldTable = nil;
}
if (HaveNew) {
newTable = &SideTables()[newObj];
} else {
newTable = nil;
}
SideTable::lockTwo<HaveOld, HaveNew>(oldTable, newTable);
if (HaveOld && *location != oldObj) {
SideTable::unlockTwo<HaveOld, HaveNew>(oldTable, newTable);
goto retry;
}
// Prevent a deadlock between the weak reference machinery
// and the +initialize machinery by ensuring that no
// weakly-referenced object has an un-+initialized isa.
if (HaveNew && newObj) {
Class cls = newObj->getIsa();
if (cls != previouslyInitializedClass &&
!((objc_class *)cls)->isInitialized())
{
SideTable::unlockTwo<HaveOld, HaveNew>(oldTable, newTable);
_class_initialize(_class_getNonMetaClass(cls, (id)newObj));
// If this class is finished with +initialize then we're good.
// If this class is still running +initialize on this thread
// (i.e. +initialize called storeWeak on an instance of itself)
// then we may proceed but it will appear initializing and
// not yet initialized to the check above.
// Instead set previouslyInitializedClass to recognize it on retry.
previouslyInitializedClass = cls;
goto retry;
}
}
// Clean up old value, if any.
if (HaveOld) {
weak_unregister_no_lock(&oldTable->weak_table, oldObj, location);
}
// Assign new value, if any.
if (HaveNew) {
newObj = (objc_object *)weak_register_no_lock(&newTable->weak_table,
(id)newObj, location,
CrashIfDeallocating);
// weak_register_no_lock returns nil if weak store should be rejected
// Set is-weakly-referenced bit in refcount table.
if (newObj && !newObj->isTaggedPointer()) {
newObj->setWeaklyReferenced_nolock();
}
// Do not set *location anywhere else. That would introduce a race.
*location = (id)newObj;
}
else {
// No new value. The storage is not changed.
}
SideTable::unlockTwo<HaveOld, HaveNew>(oldTable, newTable);
return (id)newObj;
}
添加weak 變量流程:
一個(gè)被聲明 __weak 變量的對(duì)象指針 經(jīng)過 objc_initweak()經(jīng)過一系列函數(shù)調(diào)用棧最終在 weak_register_no_lock()函數(shù)進(jìn)行弱引用變量添加,添加位置是通過哈希算法來進(jìn)行位置查找,如果經(jīng)過查找對(duì)應(yīng)位置有當(dāng)前對(duì)象所對(duì)應(yīng)的弱引用數(shù)組,就把新的弱引用變量添加到數(shù)組當(dāng)中 ,沒有新創(chuàng)建弱引用數(shù)組第一位 其他添加為nil
清除weak 變量流程:
當(dāng)一個(gè)對(duì)象被dealloc 執(zhí)行 weka_clear_no_lock(),再函數(shù)內(nèi)部根據(jù)當(dāng)前對(duì)象指針查找弱引用表,把當(dāng)前對(duì)象相對(duì)應(yīng)的弱引用都取出是個(gè)數(shù)組,遍歷數(shù)組分別置為nil