1> 什么是runtime
runtime是一套比較底層的純C語言API, 屬于1個(gè)C語言庫, 包含了很多底層的C語言API泥畅。
在我們平時(shí)編寫的OC代碼中, 程序運(yùn)行過程時(shí), 其實(shí)最終都是轉(zhuǎn)成了runtime的C語言代碼, runtime算是OC的幕后工作者,objc_msgSend
2> runtime干什么用,使用場(chǎng)景
runtime是屬于OC的底層, 可以進(jìn)行一些非常底層的操作(用OC是無法現(xiàn)實(shí)的, 不好實(shí)現(xiàn))
在程序運(yùn)行過程中, 動(dòng)態(tài)創(chuàng)建一個(gè)類(比如KVO的底層實(shí)現(xiàn)) objc_allocateClassPair何鸡,class_addIvar酌泰,objc_registerClassPair
在程序運(yùn)行過程中, 動(dòng)態(tài)地為某個(gè)類添加屬性\方法, 修改屬性值\方法(修改封裝的框架) objc_setAssociatedObject object_setIvar
遍歷一個(gè)類的所有成員變量(屬性)\所有方法(字典轉(zhuǎn)模型,歸解檔) class_copyIvarList class_copyPropertyList class_copyMethodList
(class_copyPropertyList返回的僅僅是對(duì)象類的屬性(@property申明的屬性),而class_copyIvarList返回類的所有屬性和變量(包括在@interface大括號(hào)中聲明的變量)
2.消息機(jī)制
1> 消息轉(zhuǎn)發(fā)的原理
當(dāng)向一個(gè)對(duì)象發(fā)送消息時(shí)特铝,objc_msgSend方法根據(jù)對(duì)象的isa指針找到對(duì)象的類慨仿,然后在類的調(diào)度表(dispatch table)中查找selector所坯。如果無法找到selector,objc_msgSend通過指向父類的指針找到父類锋八,并在父類的調(diào)度表(dispatch table)中查找selector浙于,以此類推直到NSObject類。一旦查找到selector挟纱,objc_msgSend方法根據(jù)調(diào)度表的內(nèi)存地址調(diào)用該實(shí)現(xiàn)羞酗。 通過這種方式,message與方法的真正實(shí)現(xiàn)在執(zhí)行階段才綁定紊服。
為了保證消息發(fā)送與執(zhí)行的效率檀轨,系統(tǒng)會(huì)將全部selector和使用過的方法的內(nèi)存地址緩存起來。每個(gè)類都有一個(gè)獨(dú)立的緩存围苫,緩存包含有當(dāng)前類自己的 selector以及繼承自父類的selector裤园。查找調(diào)度表(dispatch table)前,消息發(fā)送系統(tǒng)首先檢查receiver對(duì)象的緩存剂府。
緩存命中的情況下,消息發(fā)送(messaging)比直接調(diào)用方法(function call)只慢一點(diǎn)點(diǎn)點(diǎn)點(diǎn)剃盾。
2> SEL isa super cmd 是什么
sel: 一種類型,表示方法名稱,類似字符串(可互轉(zhuǎn))
isa:在方法底層對(duì)應(yīng)的objc_msgSend調(diào)用時(shí),會(huì)根據(jù)isa找到對(duì)象所在的類對(duì)象,類對(duì)象中包含了調(diào)度表(dispatch table),該表將類的sel和方法的實(shí)際內(nèi)存地址關(guān)聯(lián)起來
super_class:每一個(gè)類中還包含了一個(gè)super_class指針,用來指向父類對(duì)象
_cmd在Objective-C的方法中表示當(dāng)前方法的selector腺占,正如同self表示當(dāng)前方法調(diào)用的對(duì)象實(shí)例
IMP定義為 id (*IMP) (id, SEL, …)。這樣說來痒谴, IMP是一個(gè)指向函數(shù)的指針衰伯,這個(gè)被指向的函數(shù)包括id(“self”指針),調(diào)用的SEL(方法名)积蔚,再加上一些其他參數(shù).說白了IMP就是實(shí)現(xiàn)方法
3> 動(dòng)態(tài)綁定
—在運(yùn)行時(shí)確定要調(diào)用的方法
動(dòng)態(tài)綁定將調(diào)用方法的確定也推遲到運(yùn)行時(shí)意鲸。在編譯時(shí),方法的 調(diào)用并不和代碼綁定在一起尽爆,只有在消實(shí)發(fā)送出來之后怎顾,才確定被調(diào)用的代碼。通過動(dòng)態(tài)類型和動(dòng)態(tài)綁定技術(shù)漱贱,您的代碼每次執(zhí)行都可以得到不同的結(jié)果槐雾。運(yùn)行時(shí)因 子負(fù)責(zé)確定消息的接收者和被調(diào)用的方法。運(yùn)行時(shí)的消息分發(fā)機(jī)制為動(dòng)態(tài)綁定提供支持幅狮。當(dāng)您向一個(gè)動(dòng)態(tài)類型確定了的對(duì)象發(fā)送消息時(shí)募强,運(yùn)行環(huán)境系統(tǒng)會(huì)通過接收者 的isa指針定位對(duì)象的類,并以此為起點(diǎn)確定被調(diào)用的方法崇摄,方法和消息是動(dòng)態(tài)綁定的擎值。而且,您不必在Objective-C 代碼中做任何工作逐抑,就可以自動(dòng)獲取動(dòng)態(tài)綁定的好處鸠儿。您在每次發(fā)送消息時(shí),特別是當(dāng)消息的接收者是動(dòng)態(tài)類型已經(jīng)確定的對(duì)象時(shí)泵肄,動(dòng)態(tài)綁定就會(huì)例行而透明地發(fā)生捆交。