經(jīng)??吹酱a中出現(xiàn)導(dǎo)入<objc/runtime.h>,但一直處于各種理由沒有詳細(xì)了解一下,今天在馬上要回學(xué)校答辯的時(shí)候仔細(xì)的研究了下Objc Runtime。
首先,來了解一下什么是Objc Runtime?
Objective-C語言是一門動(dòng)態(tài)語言,它將很多靜態(tài)語言在編譯和鏈接時(shí)期做的事放到了運(yùn)行時(shí)來處理。這種動(dòng)態(tài)語言的優(yōu)勢(shì)在于:我們寫代碼時(shí)能夠更具靈活性,如我們可以把消息轉(zhuǎn)發(fā)給我們想要的對(duì)象,或者隨意交換一個(gè)方法的實(shí)現(xiàn)等。這種特性意味著Objective-C不僅需要一個(gè)編譯器,還需要一個(gè)運(yùn)行時(shí)系統(tǒng)來執(zhí)行編譯的代碼。對(duì)于Objective-C來說,這個(gè)運(yùn)行時(shí)系統(tǒng)就像一個(gè)操作系統(tǒng)一樣:它讓所有的工作可以正常的運(yùn)行。這個(gè)運(yùn)行時(shí)系統(tǒng)即Objc Runtime。Objc Runtime其實(shí)是一個(gè)Runtime庫,它基本上是用C和匯編寫的,這個(gè)庫使得C語言有了面向?qū)ο蟮哪芰Αuntime的強(qiáng)大之處在于它能在運(yùn)行時(shí)創(chuàng)建類和對(duì)象。
Objective-C類是由Class類型來表示的,它實(shí)際上是一個(gè)指向objc_class結(jié)構(gòu)體的指針。它的定義如下:
typedef struct objc_class *Class;
因?yàn)楝F(xiàn)在的objc是2.0,所以上述的Class可以簡(jiǎn)化為:
struct objc_class {
Class isa;
}
基本概念
對(duì)于現(xiàn)在絕大多數(shù)的64位系統(tǒng)而言,我們接觸到的都是ObjC2.0的modern runtime。ObjC程序從3個(gè)層次來使用到runtime:
1.ObjC源碼
這說明了runtime是ObjC的基石,你定義的類/方法/協(xié)議等等,最后都需要使用到runtime。其中,最重要的部分就是方法的messaging。
2.ObjC方法(Method)
絕大多數(shù)ObjC都繼承自NSObject,他們都可以在運(yùn)行的時(shí)候檢查屬于/繼承哪個(gè)類,某個(gè)對(duì)象是否有某個(gè)方法,是否實(shí)現(xiàn)了某個(gè)協(xié)議等等。這一部分是編程時(shí),經(jīng)常會(huì)使用到的。
3.ObjC函數(shù)(Function)
Runtime相關(guān)的頭文件在: /usr/include/objc中,我們可以使用其中定義的對(duì)象和函數(shù)。通常情況下,我們很少會(huì)使用到。但個(gè)別情況我們可能需要使用,比如swizzling。此外,這些純C的實(shí)現(xiàn)說明了我們可以用C來實(shí)現(xiàn)ObjC的方法。
Messaging
之前說過,所有的ObjC方法最后都通過runtime實(shí)現(xiàn),這都是通過調(diào)用函數(shù)objc_msgSend. 也就是說諸如:
[receiver doSomething] 的調(diào)用最終都是展開調(diào)用objc_msgSend完成的。 在此之前,先看下ObjC的class定義:

因?yàn)楝F(xiàn)在的objc是2.0,所以上述的Class可以簡(jiǎn)化為:
struct objc_class {Class isa;}
Class只是一個(gè)包含了指向自身結(jié)構(gòu)體的isa指針的結(jié)構(gòu)體,雖然這個(gè)結(jié)構(gòu)體具體的內(nèi)容沒有找到定義,但是根據(jù)頭文件里的寫法我們可以猜測(cè),它必定還包含父類,變量,方法,協(xié)議等信息(最新的runtime信息可以在opensource中查看)。
導(dǎo)入runtime后如何簡(jiǎn)單使用:

objc_getAssociatedObject? 相當(dāng)于iOS內(nèi)部的get方法
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
OSX_AVAILABLE_STARTING(MAC_10_6, __IPHONE_3_1);
1.id object :? 關(guān)聯(lián)對(duì)象
2.const voidkey: 我們需要定義一個(gè)常量void類型的key
objc_setAssociatedObject? 相當(dāng)于iOS的屬性的set方法
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
OSX_AVAILABLE_STARTING(MAC_10_6, __IPHONE_3_1);
1.id object :被關(guān)聯(lián)的對(duì)象
2.const void *key? :char 類型的key
3.id value? :要被賦值的值
4.objc_AssociationPolicy policy :runtime內(nèi)存管理有一下集幾種

OBJC_EXPORT void objc_removeAssociatedObjects(id object)
OSX_AVAILABLE_STARTING(MAC_10_6, __IPHONE_3_1);
id object: 移除關(guān)聯(lián)對(duì)象,用法不是很難,但是在使用中最好是合理使用,