iOS weak的實現(xiàn)原理和load和initialize的區(qū)別

1.不得不知的load與initialize

總結(jié):

load和initialize的共同點

1.如果父類和子類都被調(diào)用,父類的調(diào)用一定在子類之前

+load方法要點

當(dāng)類被引用進項目的時候就會執(zhí)行l(wèi)oad函數(shù)(在main函數(shù)開始執(zhí)行之前),與這個類是否被用到無關(guān),每個類的load函數(shù)只會自動調(diào)用一次.由于load函數(shù)是系統(tǒng)自動加載的,因此不需要再調(diào)用[super load],否則父類的load函數(shù)會多次執(zhí)行考传。

1.當(dāng)父類和子類都實現(xiàn)load函數(shù)時,父類的load方法執(zhí)行順序要優(yōu)先于子類
2.當(dāng)一個類未實現(xiàn)load方法時,不會調(diào)用父類load方法
3.類中的load方法執(zhí)行順序要優(yōu)先于類別(Category)
4.當(dāng)有多個類別(Category)都實現(xiàn)了load方法,這幾個load方法都會執(zhí)行,但執(zhí)行順序不確定(其執(zhí)行順序與類別在Compile Sources中出現(xiàn)的順序一致)
5.當(dāng)然當(dāng)有多個不同的類的時候,每個類load 執(zhí)行順序與其在Compile Sources出現(xiàn)的順序一致

注意:

load調(diào)用時機比較早,當(dāng)load調(diào)用時,其他類可能還沒加載完成,運行環(huán)境不安全.
load方法是線程安全的戳葵,它使用了鎖筋量,我們應(yīng)該避免線程阻塞在load方法.

+initialize方法要點

initialize在類或者其子類的第一個方法被調(diào)用前調(diào)用植袍。即使類文件被引用進項目,但是沒有使用,initialize不會被調(diào)用筋遭。由于是系統(tǒng)自動調(diào)用打颤,也不需要顯式的調(diào)用父類的initialize,否則父類的initialize會被多次執(zhí)行漓滔。假如這個類放到代碼中编饺,而這段代碼并沒有被執(zhí)行,這個函數(shù)是不會被執(zhí)行的次和。

1.父類的initialize方法會比子類先執(zhí)行
2.當(dāng)子類不實現(xiàn)initialize方法反肋,會把父類的實現(xiàn)繼承過來調(diào)用一遍那伐。在此之前踏施,父類的方法會被優(yōu)先調(diào)用一次
3.當(dāng)有多個Category都實現(xiàn)了initialize方法,會覆蓋類中的方法,只執(zhí)行一個(會執(zhí)行Compile Sources 列表中最后一個Category 的initialize方法)

注意:

在initialize方法收到調(diào)用時,運行環(huán)境基本健全石蔗。
initialize內(nèi)部也使用了鎖,所以是線程安全的畅形。但同時要避免阻塞線程养距,不要再使用鎖

2weak的實現(xiàn)原理:

weak基本用法

weak是弱引用,用weak描述修飾或者所引用對象的計數(shù)器不會加一日熬,并且會在引用的對象被釋放的時候自動被設(shè)置為nil棍厌,大大避免了野指針訪問壞內(nèi)存引起崩潰的情況,另外weak還可以用于解決循環(huán)引用竖席。

weak原理概括

weak表其實是一個hash(哈希)表耘纱,Key是所指對象的地址,Value是weak指針的地址數(shù)組毕荐。weak的底層實現(xiàn)的原理是什么束析?

Runtime維護了一個weak表,用于存儲指向某個對象的所有weak指針憎亚。weak表其實是一個hash表员寇,Key是所指對象的地址,value是weak指針的地址(這個地址的值是所指對象指針的地址)數(shù)組第美。

為什么value是數(shù)組蝶锋?因為一個對象可能被多個弱引用指針指向

WEAK原理實現(xiàn)步驟

weak 的實現(xiàn)原理可概括三步:

1.初始化時:

runtime會調(diào)用objc_initWeak函數(shù),初始化一個新的weak指針指向?qū)ο蟮牡刂贰?/p>

初始化流程圖.png

2.添加引用時:

objc_initWeak函數(shù)會調(diào)用 objc_storeWeak() 函數(shù)什往, objc_storeWeak() 的作用是更新指針指向扳缕,創(chuàng)建對應(yīng)的弱引用表。


更新指針,創(chuàng)建弱引用表.png

3.釋放時

調(diào)用clearDeallocating函數(shù)别威。clearDeallocating函數(shù)首先根據(jù)對象地址獲取所有weak指針地址的數(shù)組第献,然后遍歷這個數(shù)組把其中的數(shù)據(jù)設(shè)為nil,最后把這個entry從weak表中刪除兔港,最后清理對象的記錄庸毫。

weak實現(xiàn)三步驟詳細(xì)過程:

1、初始化時:

runtime會調(diào)用objc_initWeak函數(shù)衫樊,objc_initWeak函數(shù)會初始化一個新的weak指針指向?qū)ο蟮牡刂贰?/p>

示例代碼:

NSObject *obj = [[NSObject alloc] init];
id __weak obj1 = obj;

當(dāng)我們初始化一個weak變量時飒赃,runtime會調(diào)用 NSObject.mm 中的objc_initWeak函數(shù)。

這個函數(shù)在Clang中的聲明如下:

id objc_initWeak(id *object, id value);

而對于 objc_initWeak() 方法的實現(xiàn)如下:

id objc_initWeak(id location, id newObj) {
// 查看對象實例是否有效,無效對象直接導(dǎo)致指針釋放
if (!newObj) {
location = nil;
return nil;
}
// 這里傳遞了三個 bool 數(shù)值
// 使用 template 進行常量參數(shù)傳遞是為了優(yōu)化性能
return storeWeakfalse/
old
/, true/new/, true/crash/>
(location, (objc_object*)newObj);
}

這里先判斷了其指針指向的類對象是否有效科侈,無效直接釋放返回载佳,不再往深層調(diào)用函數(shù)。否則臀栈,object將通過bjc_storeWeak函數(shù)被注冊為一個指向value的__weak對象蔫慧。

注意:

objc_initWeak函數(shù)有一個前提條件:就是object必須是一個沒有被注冊為__weak對象的有效指針。而value則可以是null权薯,或者指向一個有效的對象姑躲。

2睡扬、添加引用時:

objc_initWeak函數(shù)會調(diào)用 objc_storeWeak() 函數(shù), objc_storeWeak() 的作用是更新指針指向黍析,創(chuàng)建對應(yīng)的弱引用表卖怜。

objc_storeWeak的函數(shù)聲明如下:

id objc_storeWeak(id *location, id value);

objc_storeWeak() 的具體實現(xiàn),請參考weak弱引用實現(xiàn)的方式,這里的實現(xiàn)很復(fù)雜阐枣,沒看懂马靠,沒看懂。

3蔼两、釋放時

調(diào)用clearDeallocating函數(shù)甩鳄。clearDeallocating函數(shù)首先根據(jù)對象地址獲取所有weak指針地址的數(shù)組,然后遍歷這個數(shù)組把其中的數(shù)據(jù)設(shè)為nil额划,最后把這個entry從weak表中刪除娩贷,最后清理對象的記錄。

當(dāng)weak引用指向的對象被釋放時锁孟,又是如何去處理weak指針的呢彬祖?當(dāng)釋放對象時,其基本流程如下:
1品抽、調(diào)用objc_release
2储笑、因為對象的引用計數(shù)為0,所以執(zhí)行dealloc
3圆恤、在dealloc中突倍,調(diào)用了_objc_rootDealloc函數(shù)
4、在_objc_rootDealloc中盆昙,調(diào)用了object_dispose函數(shù)
5羽历、調(diào)用objc_destructInstance
6、最后調(diào)用objc_clear_deallocating,詳細(xì)過程如下:
a. 從weak表中獲取廢棄對象的地址為鍵值的記錄
b. 將包含在記錄中的所有附有 weak修飾符變量的地址淡喜,賦值為 nil
c. 將weak表中該記錄刪除
d. 從引用計數(shù)表中刪除廢棄對象的地址為鍵值的記錄

拓展補充

weak秕磷,__unsafe_unretained, unowned 與 assign區(qū)別

  • __unsafe_unretained: 不會對對象進行retain,當(dāng)對象銷毀時,會依然指向之前的內(nèi)存空間(野指針)
  • weak: 不會對對象進行retain,當(dāng)對象銷毀時,會自動指向nil
  • assign: 實質(zhì)與__unsafe_unretained等同
  • unsafe_unretained也可以修飾代表簡單數(shù)據(jù)類型的property,weak也不能修飾用來代表簡單數(shù)據(jù)類型的property炼团。
  • __unsafe_unretained 與 weak 比較澎嚣,使用 weak 是有代價的,因為通過上面的原理可知瘟芝,__weak需要檢查對象是否已經(jīng)消亡易桃,而為了知道是否已經(jīng)消亡,自然也需要一些信息去跟蹤對象的使用情況锌俱。也正因此晤郑,__unsafe_unretained 比 __weak快,所以當(dāng)明確知道對象的生命期時,選擇__unsafe_unretained 會有一些性能提升,這種性能提升是很微小的造寝。但當(dāng)很清楚的情況下磕洪,__unsafe_unretained 也是安全的,自然能快一點是一點匹舞。而當(dāng)情況不確定的時候,應(yīng)該優(yōu)先選用 __weak 线脚。
  • unowned使用在Swift中赐稽,也會分 weak 和 unowned。unowned 的含義跟 __unsafe_unretained 差不多浑侥。假如很明確的知道對象的生命期姊舵,也可以選擇 unowned。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末寓落,一起剝皮案震驚了整個濱河市括丁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌伶选,老刑警劉巖史飞,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異仰税,居然都是意外死亡构资,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進店門陨簇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吐绵,“玉大人,你說我怎么就攤上這事河绽〖旱ィ” “怎么了?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵耙饰,是天一觀的道長纹笼。 經(jīng)常有香客問我,道長苟跪,這世上最難降的妖魔是什么允乐? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮削咆,結(jié)果婚禮上牍疏,老公的妹妹穿的比我還像新娘。我一直安慰自己拨齐,他們只是感情好鳞陨,可當(dāng)我...
    茶點故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布错森。 她就那樣靜靜地躺著,像睡著了一般官辈。 火紅的嫁衣襯著肌膚如雪稿茉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天掏导,我揣著相機與錄音享怀,去河邊找鬼。 笑死趟咆,一個胖子當(dāng)著我的面吹牛添瓷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播值纱,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼鳞贷,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了虐唠?” 一聲冷哼從身側(cè)響起搀愧,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎疆偿,沒想到半個月后咱筛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡杆故,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年眷蚓,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片反番。...
    茶點故事閱讀 40,444評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡沙热,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出罢缸,到底是詐尸還是另有隱情篙贸,我是刑警寧澤,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布枫疆,位于F島的核電站爵川,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏息楔。R本人自食惡果不足惜寝贡,卻給世界環(huán)境...
    茶點故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望值依。 院中可真熱鬧圃泡,春花似錦、人聲如沸愿险。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至风秤,卻和暖如春鳖目,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缤弦。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工领迈, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人碍沐。 一個月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓狸捅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親抢韭。 傳聞我的和親對象是個殘疾皇子薪贫,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,455評論 2 359

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