weak 筆記

weak

weak 是弱引用(不持有),與 strong 相對。

內(nèi)部實現(xiàn)

Runtime 維護著一個全局的哈希表,即由自旋鎖控制的弱引用表(weak_table_t),以對象地址為key,以指向?qū)ο蟮娜跻玫纳⒘屑蠟関alue。

// 全局弱引用表
struct weak_table_t {
    weak_entry_t *weak_entries; // 所有的弱引用記錄
};
// 弱引用結(jié)構(gòu)體
struct weak_entry_t {
    DisguisedPtr<objc_object> referent; // 對象
    struct {
        weak_referrer_t *referrers; // 所有指向?qū)ο蟮闹羔樀刂?    };
};
// 指向弱引用對象的指針的地址
typedef objc_object ** weak_referrer_t;

當(dāng)對象被釋放調(diào)用 dealloc 方法后

  1. 通過對象地址獲取全局 weak 哈希表中的記錄。
  2. for循環(huán)遍歷 weak 指針數(shù)組中的指針并置為nil,并從哈希表中移除。

調(diào)用路徑:

// NSObject.mm
- (void)dealloc {
    _objc_rootDealloc(self);
}
void _objc_rootDealloc(id obj){
    obj->rootDealloc();
}

// objc-object.h
inline void objc_object::rootDealloc(){
    object_dispose((id)this);
}

// objc-runtime-new.mm
id object_dispose(id obj){
    objc_destructInstance(obj);
}
void *objc_destructInstance(id obj) {
    if (assoc) _object_remove_assocations(obj); // 刪除關(guān)聯(lián)對象
    if (dealloc) obj->clearDeallocating(); // 回收
}

// objc-object.h
inline void objc_object::clearDeallocating(){
    clearDeallocating_slow();
}

// NSObject.mm
NEVER_INLINE void objc_object::clearDeallocating_slow(){
    if (isa.weakly_referenced) { // 包含弱引用
        weak_clear_no_lock(&table.weak_table, (id)this); 
    }
}

// objc-weak.mm
void weak_clear_no_lock(weak_table_t *weak_table, id referent_id){
    // for 循環(huán)遍歷設(shè)置指針為nil后,刪除。
}

OC 中向 nil 發(fā)送方法是安全的。

相關(guān)問題

  1. 使用weak的情景

    • 在 ARC 下,遇到循環(huán)引用問題是,使一方使用 weak 修飾。例如:delegate。
    • 本身已經(jīng)有了強引用時,可以使用weak。例如:xib或者storyboard中的控件屬性一般使用weak。
  2. weak 與 assign

    weak 弱持有對象,對象銷毀時,屬性值也跟著銷毀,必須用于 OC 對象。assign 只進行簡單賦值操作,一般用于基礎(chǔ)類型數(shù)據(jù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容