Runtime簡介Objective-C runtime 運(yùn)行 native code 。Java VM 運(yùn)行 byte code,。 原生碼(native code)又稱為機(jī)器碼(machine code),,是電腦的CPU可直接解讀的數(shù)據(jù),,是計(jì)算機(jī)可以直接執(zhí)行,執(zhí)行速度最快的代碼,。 字節(jié)碼(byte code)碼是一種中間狀態(tài)(中間碼)的二進(jìn)制代碼(文件),。需要轉(zhuǎn)譯后才能成為機(jī)器碼。 比如java:字節(jié)碼在運(yùn)行時(shí)通過JVM(JAVA虛擬機(jī))做一次轉(zhuǎn)換生成機(jī)器指令,,因此能夠更好的跨平臺(tái)運(yùn)行,。 Objc Runtime其實(shí)是一個(gè)Runtime庫,它基本上是用C和匯編寫的,,這個(gè)庫使得C語言有了面向?qū)ο蟮哪芰Α?/p> 在Runtime中,,對(duì)象可以用C語言中的結(jié)構(gòu)體表示,而方法可以用C函數(shù)來實(shí)現(xiàn),,另外再加上了一些額外的特性,。這些結(jié)構(gòu)體和函數(shù)被runtime函數(shù)封裝后,讓OC的面向?qū)ο缶幊套優(yōu)榭赡堋?/p> 當(dāng)程序執(zhí)行[object doSomething]時(shí),,會(huì)向消息接收者(object)發(fā)送一條消息(doSomething),,runtime會(huì)根據(jù)消息接收者是否能響應(yīng)該消息而做出不同的反應(yīng)。 動(dòng)態(tài)語言靜態(tài)類型語言:指在編譯期間就去做數(shù)據(jù)類型檢查,,多數(shù)靜態(tài)類型語言要求在使用變量之前必須聲明數(shù)據(jù)類型,。比如C#,Java,。 動(dòng)態(tài)類型語言:指在運(yùn)行期間才去做數(shù)據(jù)類型檢查,,也就是說,用動(dòng)態(tài)語言編程時(shí),,永遠(yuǎn)不用去給任何變量去指定數(shù)據(jù)類型,。該語言會(huì)在你第一次給該變量賦值的時(shí)候,在內(nèi)部把數(shù)據(jù)類型記錄下來,。JavaScript、ruby或者Python是典型的動(dòng)態(tài)類型的語言,。 OC語言,,編譯階段并不能決定真正調(diào)用哪個(gè)函數(shù),只要函數(shù)聲明過即使沒有實(shí)現(xiàn)也不會(huì)報(bào)錯(cuò),。 我們常說OC是一門動(dòng)態(tài)語言,,就是因?yàn)樗偸前岩恍Q定性的工作從編譯階段推遲到運(yùn)行時(shí)階段。OC代碼的運(yùn)行不僅需要編譯器,,還需要運(yùn)行時(shí)系統(tǒng)(Runtime)來執(zhí)行編譯后的代碼,。 Runtime是一套底層純C語言API,OC代碼最終都會(huì)被編譯器轉(zhuǎn)化為運(yùn)行時(shí)代碼,通過消息機(jī)制決定函數(shù)調(diào)用方式,,這也是OC作為動(dòng)態(tài)語言使用的基礎(chǔ),。 isa在Objective-C中,任何類的定義都是對(duì)象,。類和類的實(shí)例(對(duì)象)沒有任何本質(zhì)上的區(qū)別,。任何對(duì)象都有isa指針。 isa:是類指針,,之所以說isa是指針是因?yàn)镃lass其實(shí)是一個(gè)指向objc_class結(jié)構(gòu)體的指針,而isa 是它唯一的私有成員變量,即所有對(duì)象都有isa指針(isa位置在成員變量第一個(gè)位置) objc_class是個(gè)結(jié)構(gòu)體,,而且第一個(gè)成員變量也是isa指針,這個(gè)指針指向的Class不是指向自己而是metaclass(元類) metaclass每個(gè)實(shí)例對(duì)象也就是struct objc_object結(jié)構(gòu)體它的isa的指針指向類對(duì)象Class,,而Class里也有個(gè)isa的指針, 指向metaClass(元類),。 元類是類對(duì)象的類,類對(duì)象是元類的實(shí)例,。 這時(shí)候相對(duì)于元類,,objc_class就是元類的實(shí)例對(duì)象。 基于這種設(shè)計(jì)模式,,不難發(fā)現(xiàn):
看圖說話: 1. objc_object中的isa指的是對(duì)象的類,。 2. objc_class中的isa指的是類的元類。 3. superClass是一層層集成的,,到最后NSObject的superClass是nil,。而NSObject的isa指向根元類,這個(gè)根元類的isa指向它自己,,而它的superClass是NSObject,也就是最后形成一個(gè)環(huán),。 4. metaClass也是相互繼承的。 5. 從objc_class結(jié)構(gòu)體可以看出來,,里面有個(gè)isa屬性,,還有個(gè)super_class屬性,它倆都是指針,,其實(shí)在objc_class的定義中也能看出來,,每一個(gè)objc_class都有isa,但是不一定會(huì)有super_class。 重點(diǎn)總結(jié): meta-class也是一個(gè)類,,也可以向它發(fā)送一個(gè)消息,,那么它的isa又是指向什么呢,?為了不讓這種結(jié)構(gòu)無限延伸下去,Objective-C的設(shè)計(jì)者讓所有的meta-class的isa指向基類的meta-class,,以此作為它們的所屬類。即,,任何NSObject繼承體系下的meta-class都使用NSObject的meta-class作為自己的所屬類,而基類的meta-class的isa指針是指向它自己,。這樣就形成了一個(gè)完美的閉環(huán),。 方法在 objc-runtime-new.h中定義: struct method_t { SEL name; const char *types; IMP imp; struct SortBySELAddress : public std::binary_function 我們說下上面代碼中的SEL和IMP,。 SEL:表示該方法的名稱,, IMP: 指向該方法的具體實(shí)現(xiàn)的函數(shù)指針。 SEL 的含義: typedef struct objc_selector *SEL; 它是一個(gè)指向 objc_selector 指針,,表示方法的名字/簽名,。如下所示,打印出 selector,,會(huì)打印出來方法的名稱。 不同類的實(shí)例對(duì)象performSelector相同的 selector 時(shí),,會(huì)在各自的消息選標(biāo)(selector)/實(shí)現(xiàn)地址(address) 方法鏈表中根據(jù) selector 去查找具體的方法實(shí)現(xiàn)IMP, 然后用這個(gè)方法實(shí)現(xiàn)去執(zhí)行具體的實(shí)現(xiàn)代碼,。這是一個(gè)動(dòng)態(tài)綁定的過程,在編譯的時(shí)候,,我們不知道最終會(huì)執(zhí)行哪一些代碼,,只有在執(zhí)行的時(shí)候,通過selector去查詢,,我們才能確定具體的執(zhí)行代碼,。 IMP 的含義: 在前面我們也看到 IMP 的定義為: typedef id (*IMP)(id, SEL, ...); id是一個(gè)指向 objc_object 結(jié)構(gòu)體的指針,任何繼承自 NSObject 的類對(duì)象都可以用id 來指代,,因?yàn)?NSObject 的第一個(gè)成員實(shí)例就是isa,。 IMP 是一個(gè)函數(shù)指針,這個(gè)被指向的函數(shù)包含一個(gè)接收消息的對(duì)象id(self 指針), 調(diào)用方法的選標(biāo) SEL (方法名),,以及不定個(gè)數(shù)的方法參數(shù),,并返回一個(gè)id。也就是說 IMP 是消息最終調(diào)用的執(zhí)行代碼,是方法真正的實(shí)現(xiàn)代碼 ,。我們可以像在C語言里面一樣使用這個(gè)函數(shù)指針,。 NSObject 類中的methodForSelector:方法就是這樣一個(gè)獲取指向方法實(shí)現(xiàn)IMP 的指針,methodForSelector:返回的指針和賦值的變量類型必須完全一致,,包括方法的參數(shù)類型和返回值類型,。 IMP實(shí)際上是一個(gè)函數(shù)指針,指向方法實(shí)現(xiàn)的地址,。 Method用于表示類定義中的方法,,則定義如下: typedef struct objc_method *Methodstruct objc_method{ SEL method_name OBJC2_UNAVAILABLE; // 方法名 char *method_types OBJC2_UNAVAILABLE; IMP method_imp OBJC2_UNAVAILABLE; // 方法實(shí)現(xiàn)} 我們可以看到該結(jié)構(gòu)體中包含一個(gè)SEL和IMP,實(shí)際上相當(dāng)于在SEL和IMP之間作了一個(gè)映射,。有了SEL,,我們便可以找到對(duì)應(yīng)的IMP,從而調(diào)用方法的實(shí)現(xiàn)代碼,。 |
|