iOS +load 與 +initialize

概述

Objective-C作為一門面向對象語言鹃栽,有類和對象的概念。編譯后躯畴,類相關的數(shù)據(jù)結構會保留在目標文件中民鼓,在運行時得到解析和使用。在應用程序運行起來的時候蓬抄,類的信息會有加載和初始化過程丰嘉。

就像Application有生命周期回調方法一樣,在Objective-C的類被加載和初始化的時候嚷缭,也可以收到方法回調饮亏,可以在適當?shù)那闆r下做一些定制處理。而這正是load和initialize方法可以幫我們做到的峭状。

+ (void)load;
+ (void)initialize;

可以看到這兩個方法都是以“+”開頭的類方法克滴,返回為空。通常情況下优床,我們在開發(fā)過程中可能不必關注這兩個方法。如果有需要定制誓焦,我們可以在自定義的NSObject子類中給出這兩個方法的實現(xiàn)胆敞,這樣在類的加載和初始化過程中,自定義的方法可以得到調用杂伟。

+load

顧名思義移层,+load方法在這個文件被程序裝載時調用。只要是在Compile Sources中出現(xiàn)的文件總是會被裝載赫粥,這與這個類是否被用到無關观话,因此+load方法總是在main函數(shù)之前調用。

調用方式:

會循環(huán)調用所有類的 +load 方法越平。注意频蛔,這里是(調用分類的 +load 方法也是如此)直接使用函數(shù)內存地址的方式 (*load_method)(cls, SEL_load); 對 +load 方法進行調用的,而不是使用發(fā)送消息 objc_msgSend 的方式秦叛。

這樣的調用方式就使得 +load 方法擁有了一個非常有趣的特性晦溪,那就是子類、父類和分類中的 +load 方法的實現(xiàn)是被區(qū)別對待的挣跋。也就是說如果子類沒有實現(xiàn) +load 方法三圆,那么當它被加載時 runtime 是不會去調用父類的 +load 方法的。同理,當一個類和它的分類都實現(xiàn)了 +load 方法時舟肉,兩個方法都會被調用修噪。

要點:

  • 調用時機比較早,運行環(huán)境有不確定因素路媚。具體說來黄琼,在iOS上通常就是App啟動時進行加載,但當load調用的時候磷籍,并不能保證所有類都加載完成且可用适荣,必要時還要自己負責做auto release處理。
    補充上面一點院领,對于有依賴關系的兩個庫中弛矛,被依賴的類的+load會優(yōu)先調用。但在一個庫之內比然,父丈氓、子類、類別之間調用有順序强法,不同類之間調用順序是不確定的万俗。
  • 關于繼承:對于一個類而言,沒有+load方法實現(xiàn)就不會調用饮怯,不會考慮對NSObject的繼承闰歪,就是不會沿用父類的+load。
  • 父類和本類的調用:父類的方法優(yōu)先于子類的方法蓖墅。一個類的+load方法不用寫明[super load]库倘,父類就會收到調用。
  • 本類和Category的調用:本類的方法優(yōu)先于類別(Category)中的方法论矾。Category的+load也會收到調用教翩,但順序上在本類的+load調用之后。
  • 不會直接觸發(fā)initialize的調用贪壳。

+initialize

+initialize 方法是在類或它的子類收到第一條消息之前被調用的饱亿,這里所指的消息包括實例方法和類方法的調用,并且只會調用一次闰靴。initialize方法實際上是一種惰性調用彪笼,也就是說如果一個類一直沒被用到,那它的initialize方法也不會被調用传黄,這一點有利于節(jié)約資源杰扫。

調用方式:

runtime 使用了發(fā)送消息 objc_msgSend 的方式對 +initialize 方法進行調用。也就是說 +initialize 方法的調用與普通方法的調用是一樣的膘掰,走的都是發(fā)送消息的流程章姓。換言之佳遣,如果子類沒有實現(xiàn) +initialize 方法,那么繼承自父類的實現(xiàn)會被調用凡伊;如果一個類的分類實現(xiàn)了 +initialize 方法零渐,那么就會對這個類中的實現(xiàn)造成覆蓋。

要點:

  • initialize的自然調用是在第一次主動使用當前類的時候系忙。
  • 在initialize方法收到調用時诵盼,運行環(huán)境基本健全。
  • 關于繼承:和load不同银还,即使子類不實現(xiàn)initialize方法风宁,會把父類的實現(xiàn)繼承過來調用一遍,就是會沿用父類的+initialize蛹疯。(沿用父類的方法中戒财,self還是指子類)
  • 父類和本類的調用:子類的+initialize將要調用時會激發(fā)父類調用的+initialize方法,所以也不需要在子類寫明[super initialize]捺弦。(本著除主動調用外饮寞,只會調用一次的原則,如果父類的+initialize方法調用過了列吼,則不會再調用)
  • 本類和Category的調用:Category中的+initialize方法會覆蓋本類的方法幽崩,只執(zhí)行一個Category的+initialize方法。

類別(Category)

對于+initialize寞钥,只有最后一個類別執(zhí)行慌申,本類的+initialize和前面類別的+initialize被隱藏。

而對于+load理郑,本類和本類的所有類別都執(zhí)行太示,并且如果Apple的文檔中介紹順序一樣:先執(zhí)行類自身的實現(xiàn),再執(zhí)行類別中的實現(xiàn)香浩。

擴展

因為兩個方法只會被系統(tǒng)調用一次(除主動調用外),并且是線程安全的臼勉,可以用來作為單例的實現(xiàn)邻吭。(可以用+initialize,+load有些隱患宴霸,看這里

?注意

  • 在使用時都不要過重地依賴于這兩個方法囱晴,除非真正必要。
  • 謹慎在分類中實現(xiàn)+initialize方法瓢谢,因為如果在分類中實現(xiàn)了畸写,本類實現(xiàn)的+initialize方法將不會被調用。
  • 謹慎在分類中實現(xiàn)+load方法氓扛。因為如果在本類中實現(xiàn)+load方法混淆A枯芬、B兩個方法论笔,分類中也混淆A、B千所,因為本類和分類的+load都實現(xiàn)了狂魔,所以都會調用,A淫痰、B在本類中置換后最楷,又在分類中置換了回來。
  • load方法通常用來進行Method Swizzle待错,initialize方法一般用于初始化全局變量或靜態(tài)變量籽孙。
  • load和initialize方法內部使用了鎖,因此它們是線程安全的火俄。實現(xiàn)時要盡可能保持簡單犯建,避免阻塞線程,不要再使用鎖烛占。

問題

問題:

  1. 子類胎挎、父類、分類中的相應方法什么時候會被調用忆家?
  2. 需不需要在子類的實現(xiàn)中顯式地調用父類的實現(xiàn)犹菇?

解答:

  1. super的方法會成功調用,但是這是多余的芽卿,因為runtime會自動對父類的+load方法進行調用揭芍,而+initialize則會隨子類自動激發(fā)父類的方法(如Apple文檔中所言)不需要顯示調用。另一方面卸例,如果父類中的方法用到的self(像示例中的方法)称杨,其指代的依然是類自身,而不是父類筷转。

總結

+load +initialize
調用時機 被添加到 runtime 時 到第一條消息前姑原,可能永遠不調用
同一個類,調用次數(shù)
(不考慮主動調用)
1次 1次
調用順序 父類->本類->分類 父類->本類(如果有分類呜舒,則調用分類)
若自身未實現(xiàn)锭汛,是否沿用父類的方法?
類別中的定義 全都執(zhí)行袭蝗,但后于本類的方法 覆蓋本類的方法唤殴,只執(zhí)行一個
線程安全 安全 安全

結束語

可以看運行demo查看log

參考

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末到腥,一起剝皮案震驚了整個濱河市朵逝,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌乡范,老刑警劉巖配名,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啤咽,死亡現(xiàn)場離奇詭異,居然都是意外死亡段誊,警方通過查閱死者的電腦和手機闰蚕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來连舍,“玉大人没陡,你說我怎么就攤上這事∷魃停” “怎么了盼玄?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長潜腻。 經常有香客問我埃儿,道長,這世上最難降的妖魔是什么融涣? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任童番,我火速辦了婚禮,結果婚禮上威鹿,老公的妹妹穿的比我還像新娘剃斧。我一直安慰自己,他們只是感情好忽你,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布幼东。 她就那樣靜靜地躺著,像睡著了一般科雳。 火紅的嫁衣襯著肌膚如雪根蟹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天糟秘,我揣著相機與錄音简逮,去河邊找鬼。 笑死尿赚,一個胖子當著我的面吹牛买决,可吹牛的內容都是我干的。 我是一名探鬼主播吼畏,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼嘁灯!你這毒婦竟也來了泻蚊?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤丑婿,失蹤者是張志新(化名)和其女友劉穎性雄,沒想到半個月后没卸,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡秒旋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年约计,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片迁筛。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡煤蚌,死狀恐怖,靈堂內的尸體忽然破棺而出细卧,到底是詐尸還是另有隱情尉桩,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布贪庙,位于F島的核電站蜘犁,受9級特大地震影響,放射性物質發(fā)生泄漏止邮。R本人自食惡果不足惜这橙,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望导披。 院中可真熱鬧屈扎,春花似錦、人聲如沸盛卡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽滑沧。三九已至并村,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間滓技,已是汗流浹背哩牍。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留令漂,地道東北人膝昆。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像叠必,于是被迫代替她去往敵國和親荚孵。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內容