今天博主有一個runtime基礎(chǔ)的需求,遇到了一些困難點,在此和大家分享,希望能夠共同進步.
Objective-C runtime是一個運行時庫,主要是由C語言和匯編語言寫成,為C語言添加面向?qū)ο蟮哪芰Χ鴦?chuàng)造了Objective-C。這意味著它可以加載類信息,進行方法派發(fā)以及方法轉(zhuǎn)發(fā)等等。Objective-C 運行時最重要的就是為Objective-C語言的面向?qū)ο筇匦缘膶崿F(xiàn)提供了所有的基礎(chǔ)支撐.
那么,runtime具體究竟是什么呢?相信各位看官百度了很多文章后,發(fā)現(xiàn)十篇有九篇都看不懂,這時因為有很多基礎(chǔ)的東西我們并不了解,今天博主就和大家分享一下,runtime基礎(chǔ)篇
我們寫的代碼在程序運行過程中都會被轉(zhuǎn)化成runtime的C代碼執(zhí)行,例如[xxxxxx doSomething];會被轉(zhuǎn)化成objc_msgSend(xxxxxx, @selector(doSomething));
OC中一切都被設(shè)計成了對象,我們都知道一個類被初始化成一個實例,這個實例是一個對象。實際上一個類本質(zhì)上也是一個對象,在runtime中用結(jié)構(gòu)體表示。
相關(guān)的定義:
/// 描述類中的一個方法typedef struct objc_method *Method;/// 實例變量typedef struct objc_ivar *Ivar;/// 類別Categorytypedef struct objc_category *Category;/// 類中聲明的屬性typedef struct objc_PRoperty *objc_property_t;
類在runtime中的表示
//類在runtime中的表示struct objc_class { Class isa;//指針,顧名思義,表示是一個什么, //實例的isa指向類對象,類對象的isa指向元類#if !__OBJC2__ Class super_class; //指向父類 const char *name; //類名 long version; long info; long instance_size struct objc_ivar_list *ivars //成員變量列表 struct objc_method_list **methodLists; //方法列表 struct objc_cache *cache;//緩存 //一種優(yōu)化,調(diào)用過的方法存入緩存列表,下次調(diào)用先找緩存 struct objc_protocol_list *protocols //協(xié)議列表 #endif} OBJC2_UNAVAILABLE;/* Use `Class` instead of `struct objc_class *` */
相信很多看官看到這里的時候,就已經(jīng)有想關(guān)屏幕的沖動了,下面給大家分享一下isa指針和meta class(元類)

每個對象都會有一個它所屬的類。這是面向?qū)ο蟮幕靖拍?,但是在OC中,這對所有數(shù)據(jù)結(jié)構(gòu)有效。任何數(shù)據(jù)結(jié)構(gòu),只要在恰當?shù)奈恢镁哂幸粋€指針指向一個class,那么,它都可以被認為是一個對象。
在OC中,一個對象所屬于哪個類,是由它的isa指針指向的。這個isa指針指向這個對象所屬的class。
isa:是一個Class 類型的指針. 每個實例對象有個isa的指針,他指向?qū)ο蟮念?,而Class里也有個isa的指針, 指向meteClass(元類)。元類保存了類方法的列表。當類方法被調(diào)用時,先會從本身查找類方法的實現(xiàn),如果沒有,元類會向他父類查找該方法。同時注意的是:元類(meteClass)也是類,它也是對象。元類也有isa指針,它的isa指針最終指向的是一個根元類(root meteClass).根元類的isa指針指向本身,這樣形成了一個封閉的內(nèi)循環(huán)
一個OC的類其實也是一個對象,意思就是你可以向一個類發(fā)送消息。
NSStringEncoding defaultStringEncoding = [NSString defaultStringEncoding];
在這個例子中,defaultStringEncoding 被發(fā)送給了NSString類。因為每一個OC的類本身也是一個對象。也就是說Class的數(shù)據(jù)結(jié)構(gòu)必然也是以isa指針開始的在二進制級別上與objc_object是完全兼容的。然后一個類結(jié)構(gòu)的下一個字段一定是一個指向super class的指針(或者指向nil,對于基類而言)。
一個類如何定義有很多方法,依賴于你的運行時庫版本,但是不管哪種方法,他們都是以一個isa作為第一個字段,接著是superclass字段
為了可以調(diào)用類方法,這個類的isa指針必須指向一個包含這些類方法的類結(jié)構(gòu)體。
這樣就引出了meta-class的概念:meta-class是一個類對象的類。
簡單解釋下:
當你向一個對象發(fā)送消息時,runtime會在這個對象所屬的那個類的方法列表中查找。
當你向一個類發(fā)送消息時,runtime會在這個類的meta-class的方法列表中查找。
meta-class之所以重要,是因為它存儲著一個類的所有類方法。每個類都會有一個單獨的meta-class,因為每個類的類方法基本不可能完全相同
meta-class,就像Class一樣,也是一個對象。你依舊可以向它發(fā)送消息調(diào)用函數(shù),自然的,meta-class也會有一個isa指針指向其所屬類。所有的meta-class使用基類的meta-class作為他們的所屬類。具體而言,任何NSObject繼承體系下的meta-class都使用NSObject的meta-class作為自己所屬的類。
根據(jù)這個規(guī)則,所有的meta-class使用基類的meta-class作為它們的類,而基類的meta-class也是屬于它自己,也就是說基類的meta-class的isa指針指向它自己。
就像一個類使用super_class指針指向自己的父類一樣,meta-class的super_class會指向類的super_class的meta-class。一直追溯到基類的meta-class,它的super_class會指向基類自身
這樣一來,整個繼承體系中的實例、類和meta-class都派生自繼承體系中的基類。對于NSObject繼承體系來說,NSObject的實例方法對體系中所有的實例、類和meta-class都是有效的;NSObject的類方法對于體系中所有的類和meta-class都是有效的
meta-class是類對象的類,每個類都有自己單獨的meta-class。所有的類對象并不會屬于同一個meta-class。
meta-class要保證類對象具有繼承體系中基類的所有實例和類方法,以及繼承體系中的所有中間類方法。對于所有NSObject繼承體系下的類,NSObject的實例方法和協(xié)議方法對他們和他們meta-class的對象都要有效。
所有的meta-class使用基類的meta-class作為自己的基類,對于頂層基類的meta-class也是一樣,只是它指向自己而已
還有幾篇文章可以增加各位對runtime的理解
http://quotation.github.io/objc/2015/05/21/objc-runtime-ivar-access.html
http://www.jianshu.com/p/425a39d43d16?utm_campaign=maleskine&utm_content=note&utm_medium=writer_share&utm_source=weibo
http://mp.weixin.QQ.com/s?__biz=MjM5NTIyNTUyMQ==&mid=208927760&idx=1&sn=30b9caecba709553e463d719668454ae&scene=2&from=timeline&isappinstalled=0#rd
新聞熱點
疑難解答