ios weak底層實現(xiàn)

1. 從匯編探索weak

我們常用weak來進行弱引用對象,是因為它在釋放的時候自動置空胳蛮,打破循環(huán)引用销凑。

step01.png

debugDebug WorkfkowAlways Show Disassembly打開匯編調(diào)試,運行代碼:
step02.png

我們看到進行弱引用的時候調(diào)用了objc_initWeak方法仅炊,于是我們可以在添加一個符號斷點:
step03.png

添加符號斷點后斗幼,繼續(xù)往下調(diào)試,發(fā)現(xiàn)方法調(diào)用在libobjc.A.dylib庫內(nèi):
step04.png

于是抚垄,我們可以下載objc源碼進行后面的探索蜕窿。

2.源碼解析

打開源碼,發(fā)現(xiàn)objc_initWeak內(nèi)調(diào)用了storeWeak函數(shù):

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(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;
}

從源碼可看出呆馁,先對是否含有舊值新值做了判斷處理桐经,然后我們拿到一張散列表SideTable,這個散列表里維護了我們需要的weakTable智哀。當有舊值的時候次询,調(diào)用weak_unregister_no_lockoldTable內(nèi)取出weakTableweak_entry_t,并進行remove:

weak_unregister_no_lock.png

當存在新值的時候,調(diào)用weak_register_no_lock函數(shù)從newTable取出weakTable
weak_register_no_lock.png

首先判斷對象是否正在進行釋放瓷叫,如果正在進行釋放則返回nil屯吊。然后,我們從weakTable內(nèi)取出weak_entry_t摹菠,如果有值盒卸,則進行拼接到weakTable內(nèi),如果沒有值次氨,則會自己創(chuàng)建一個weak_entry_t蔽介,在插入到weakTable
最后煮寡,在返回一個新的對象虹蓄。

3 總結(jié)

1.通過SideTable找到weak_table;

2.weak_table根據(jù)referent找到或者創(chuàng)建weak_entry_t;

3.然后append_referrer(entry,referrer)將新弱引用的對象添加進去entry幸撕;

4.最后weak_entry_insert把entry加入到我們的weak_table薇组;

5.返回newObj。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末坐儿,一起剝皮案震驚了整個濱河市律胀,隨后出現(xiàn)的幾起案子宋光,更是在濱河造成了極大的恐慌,老刑警劉巖炭菌,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件罪佳,死亡現(xiàn)場離奇詭異,居然都是意外死亡黑低,警方通過查閱死者的電腦和手機赘艳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來投储,“玉大人第练,你說我怎么就攤上這事÷贶瘢” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵呕寝,是天一觀的道長勋眯。 經(jīng)常有香客問我,道長下梢,這世上最難降的妖魔是什么客蹋? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮孽江,結(jié)果婚禮上讶坯,老公的妹妹穿的比我還像新娘。我一直安慰自己岗屏,他們只是感情好辆琅,可當我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著这刷,像睡著了一般婉烟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上暇屋,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天似袁,我揣著相機與錄音,去河邊找鬼咐刨。 笑死昙衅,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的定鸟。 我是一名探鬼主播而涉,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼仔粥!你這毒婦竟也來了婴谱?” 一聲冷哼從身側(cè)響起蟹但,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谭羔,沒想到半個月后华糖,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡瘟裸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年客叉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片话告。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡兼搏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出沙郭,到底是詐尸還是另有隱情佛呻,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布病线,位于F島的核電站吓著,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏送挑。R本人自食惡果不足惜绑莺,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望惕耕。 院中可真熱鬧纺裁,春花似錦、人聲如沸司澎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽惭缰。三九已至浪南,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間漱受,已是汗流浹背络凿。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留昂羡,地道東北人絮记。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像虐先,于是被迫代替她去往敵國和親怨愤。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 原文鏈接:http://www.reibang.com/p/13c4fb1cedea 很少有人知道weak表其實...
    赫子豐閱讀 849評論 0 4
  • 前言 在iOS開發(fā)過程中蛹批,會經(jīng)常使用到一個修飾詞“weak”撰洗,使用場景大家都比較清晰篮愉,用于一些對象相互引用的時候,...
    Flame_Dream閱讀 22,836評論 3 94
  • 1.為什么要使用weak關(guān)鍵字修飾對象 因為使用weak修飾的對象在對象釋放的時候,引用它的指針會自動被置為nil...
    AryCode閱讀 3,141評論 0 9
  • 本文系轉(zhuǎn)載差导,原文地址 對于 runtime 的分析還有很長的路试躏,最近在寫 block 系列的同時,也回顧一下之前疏...
    小白猿閱讀 428評論 0 1
  • 推薦指數(shù): 6.0 書籍主旨關(guān)鍵詞:特權(quán)设褐、焦點颠蕴、注意力、語言聯(lián)想助析、情景聯(lián)想 觀點: 1.統(tǒng)計學(xué)現(xiàn)在叫數(shù)據(jù)分析犀被,社會...
    Jenaral閱讀 5,721評論 0 5