iOS中級理論知識復習(Runtime篇)

在簡書看到大牛的知識點,發(fā)現(xiàn)很多知識點自己一知半解,能做項目但理論不夠扎實,默默地去百度總結(jié)一下.放到這里和大家交流交流.

如有侵權(quán),告知即刪!


01.objc在向一個對象發(fā)送消息時,發(fā)生了什么?

objective-c 的 Runtime 鑄就了它動態(tài)語言的特性,這些深層次的知識雖然平時寫代碼用的少一些,但是卻是每個 Objc 程序員需要了解的。
Objc Runtime使得C具有了面向?qū)ο竽芰Γ诔绦蜻\行時創(chuàng)建,檢查,修改類、對象和它們的方法。可以使用runtime的一系列方法實現(xiàn)。
附上OC中一個類的底層數(shù)據(jù)結(jié)構(gòu)

struct objc_class {
    Class isa OBJC_ISA_AVAILABILITY; //isa指針指向Meta Class,因為Objc的類的本身也是一個Object,為了處理這個關(guān)系,r       untime就創(chuàng)造了Meta Class,當給類發(fā)送[NSObject alloc]這樣消息時,實際上是把這個消息發(fā)給了Class Object

    #if !__OBJC2__
    Class super_class OBJC2_UNAVAILABLE; // 父類
    const char *name OBJC2_UNAVAILABLE; // 類名
    long version OBJC2_UNAVAILABLE; // 類的版本信息,默認為0
    long info OBJC2_UNAVAILABLE; // 類信息,供運行期使用的一些位標識
    long instance_size OBJC2_UNAVAILABLE; // 該類的實例變量大小
    struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 該類的成員變量鏈表
    struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法定義的鏈表
    struct objc_cache *cache OBJC2_UNAVAILABLE; // 方法緩存,對象接到一個消息會根據(jù)isa指針查找消息對象,這時會在method       Lists中遍歷,如果cache了,常用的方法調(diào)用時就能夠提高調(diào)用的效率。
    struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 協(xié)議鏈表
    #endif

    } OBJC2_UNAVAILABLE;

OC中一個類的對象實例的[數(shù)據(jù)結(jié)構(gòu)],就是定義了一個

typedef struct objc_class *Class;

    /// Represents an instance of a class.

    struct objc_object {

        Class isa  OBJC_ISA_AVAILABILITY;

    };

    /// A pointer to an instance of a class.

    typedef struct objc_object *id;

向object發(fā)送消息時,Runtime庫會根據(jù)object的isa指針找到這個實例object所屬于的類,然后在類的方法列表以及父類方法列表尋找對應(yīng)的方法運行。id是一個objc_object結(jié)構(gòu)類型的指針,這個類型的對象能夠轉(zhuǎn)換成任何一種對象。

然后再來看看消息發(fā)送的函數(shù):objc_msgSend函數(shù)
在引言中已經(jīng)對objc_msgSend進行了一點介紹,看起來像是objc_msgSend返回了數(shù)據(jù),其實objc_msgSend從不返回數(shù)據(jù)而是你的方法被調(diào)用后返回了數(shù)據(jù)。下面詳細敘述下消息發(fā)送步驟:
1.檢測這個 selector 是不是要忽略的。比如 Mac OS X 開發(fā),有了垃圾回收就不理會 retain,release 這些函數(shù)了。
2.檢測這個 target 是不是 nil 對象。ObjC 的特性是允許對一個 nil 對象執(zhí)行任何一個方法不會 Crash,因為會被忽略掉。
3.如果上面兩個都過了,那就開始查找這個類的 IMP,先從 cache 里面找,完了 找得到就跳到對應(yīng)的函數(shù)去執(zhí)行。
4.如果 cache 找不到就找一下方法分發(fā)表。
5.如果分發(fā)表找不到就到超類的分發(fā)表去找,一直找,直到找到NSObject類為止。
6.如果還找不到就要開始進入動態(tài)方法解析了,后面會提到。


02.什么時候會報unrecognized selector錯誤?iOS有哪些機制來避免走到這一步?

當調(diào)用對象的某個方法的時候, 如果在當前類中沒有找到此方法, 那么就到當前類的父類中去尋找, 如果在父類中沒有找到, 那么就去父類的父類中去尋找, 一直找到 NSObject 都沒有這個方法, 就會報 Unrecognized selector 的異常.

但是在這之前, objc 的運行時會給出三次拯救程序崩潰的機會.

第一次: 動態(tài)添加一個新方法并執(zhí)行的機會

[objc]

+ (bool)resolveInstanceMethod:(sel)sel{  
  
}  

當系統(tǒng)第一次找不到某個方法的時候, 會自動調(diào)用這個方法, 用來給程序添加一個新方法并執(zhí)行的機會.
第二次: 當系統(tǒng)調(diào)用上一個方法后未能實現(xiàn)添加新的方法, 則系統(tǒng)會再來調(diào)用下面的這個方法, 這個方法是系統(tǒng)提供的一個將 SEL 轉(zhuǎn)給其他對象的機會

[objc]

- (id)forwardingTargetForselector:(sel)aselctor{  
  
}  

第三次: 當 forwardingTargetForselector 返回的 nil 或者 self 時, 會進入到這個方法, 這個方法是拯救程序的最后一步.
這個方法用來返回一個方法簽名, 在由后面的 forwardInvocation: 去執(zhí)行

[objc]

- (NSMethodSigature *)methodSignatrueForseletor:(sel)aselector{  
  
}  

如果上面的方法不返回 nil, 則會來到這個方法里具體執(zhí)行

[objc]

-(void)forwardInvocation:(NSInvocation *)anInvocation{  
  
  在這里會調(diào)用自己對象的其他方法, 也可以調(diào)用其他函數(shù)  
  甚至還可以調(diào)用多個不同對象的多個方法  
  
 }  

03.runtime如何實現(xiàn)weak變量的自動置nil?

要實現(xiàn) weak 屬性,首先要搞清楚 weak 屬性的特點:

weak 此特質(zhì)表明該屬性定義了一種“非擁有關(guān)系” (nonowning relationship)。為這種屬性設(shè)置新值時,設(shè)置方法既不保留新值,也不釋放舊值。此特質(zhì)同 assign 類似, 然而在屬性所指的對象遭到摧毀時,屬性值也會清空(nil out)。

那么 runtime 如何實現(xiàn) weak 變量的自動置nil?

runtime 對注冊的類, 會進行布局,對于 weak 對象會放入一個 hash 表中。 用 weak 指向的對象內(nèi)存地址作為 key,當此對象的引用計數(shù)為0的時候會 dealloc,假如 weak 指向的對象內(nèi)存地址是a,那么就會以a為鍵, 在這個 weak 表中搜索,找到所有以a為鍵的 weak 對象,從而設(shè)置為 nil。


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,247評論 6 543
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,520評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,362評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,805評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,541評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,896評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,887評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,062評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,608評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,356評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,555評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,077評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,769評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,175評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,489評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,289評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,516評論 2 379

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,755評論 0 9
  • 在表單中我們會用到上傳文件的操作,現(xiàn)就文件相關(guān)API做以下總結(jié)。文件相關(guān)的對象主要有5個。 Blob對象: 是一個...
    tiancai啊呆閱讀 1,070評論 0 0
  • 一個好習慣可以受用一輩子。這樣的道理對于大多數(shù)人來說并不陌生。但養(yǎng)成一個習慣的過程并不容易。本書就是圍繞怎樣養(yǎng)成一...
    郭振南閱讀 415評論 0 0
  • 云若V閱讀 368評論 3 1
  • 明天冰雪封山的時候 我也光著雙腳站在你翻山越嶺的盡頭 正當年少 ----宋冬野《鴿子》 愿你我既可以朝九晚五,又能...
    二兩_酋長閱讀 580評論 0 2