Runtime數(shù)據(jù)結(jié)構(gòu)(二)

在Runtime初識(shí)中,我們知曉了Runtime所能夠提供的功能温峭。那么Runtime為什么能夠提供這樣的功能呢猛铅?這就需要從消息分發(fā)機(jī)制說起。為了能夠了解消息分發(fā)凤藏,首先從數(shù)據(jù)結(jié)構(gòu)開始奸忽。

NSObject數(shù)據(jù)結(jié)構(gòu)

除了繼承自NSProxy類以外揖庄,其他的類的基類都是NSObject。首先來看下其NSObject的數(shù)據(jù)結(jié)構(gòu):
NSObject
在去除預(yù)處理指令后的定義:

@interface NSObject<NSObject>{
      Class isa OBJC_ISA_AVAILABILITY;
}

可以看出NSObject有一個(gè)Class結(jié)構(gòu)的isa屬性苛萎。這個(gè)屬性很重要,可以將其看成普通的結(jié)構(gòu)體和OC類之間的差異腌歉。凡是繼承自NSObject的類,都會(huì)有isa翘盖。如果沒有isa,那么就不是OC類了(繼承自NSProxy例外)阁危。

Class

typedef struct objc_class *Class;
struct objc_class {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
#if   !__OBJC2__
    Class _Nullable super_class       OBJC2_UNAVAILABLE;
    const char * _Nonnull name        OBJC2_UNAVAILABLE;
    long version                      OBJC2_UNAVAILABLE;
    long info                         OBJC2_UNAVAILABLE;
    long instance_size                OBJC2_UNAVAILABLE;
    struct objc_ivar_list * _Nullable * _Nullable methodLists   OBJC_UNAVAILABLE;
    struct objc_cache * _Nonnull cache    OBJC2_UNAVAILABLE;
    struct objc_protocol_list * _Nullable protocols  OBJC2_UNAVAILABLE;
#endif
}

可以看出汰瘫,Class也是含有isa指針的,可以將Class看成一個(gè)繼承自NSObject類趴乡。
Class類里面有兩個(gè)指向Class的指針。一個(gè)叫做isa晾捏,另外一個(gè)叫做super_class哀托。這兩者之間又有什么關(guān)系呢?
為了解釋清楚兩者之間的關(guān)系,現(xiàn)在引入元類的概念仓手。

  1. 每個(gè)繼承自NSObject的實(shí)例俗或,其都會(huì)存在一個(gè)isa指針指向類(Class)。
  2. 每個(gè)類依然還會(huì)有一個(gè)isa指針辛慰,其指向元類(metaClass)。
  3. 元類和類具有相同的數(shù)據(jù)結(jié)構(gòu)驰弄,但是具有不同的服務(wù)對(duì)象速客。類(Class)為實(shí)例(instance)提供服務(wù)戚篙,元類(metaClass)為類提供服務(wù)溺职。

更為具體一點(diǎn)岔擂,使用“-”開頭的實(shí)例方法都存在類里面,使用"+"開頭的方法會(huì)放在元類里面塑崖。

@interface UserClass : NSObject
@property (nonatomic) variable;//存放在實(shí)例(instance)中痛倚。
- (void)instanceMethod;   //存放在類(Class)中。
+ (void)classMethod;   //存放元類(metaClass)中抒蚜。
@end 

由此可以看出耘戚,一個(gè)通常意義下的類可以被分解成3個(gè)部分:實(shí)例(instance),實(shí)例方法區(qū)(Class)毕莱,類方法區(qū)(metaClass)颅夺。所以不用被Class這個(gè)名字所迷惑了,實(shí)際上它是存放類的方法和一些其他元數(shù)據(jù)的地方部服,只是我們通常所說類的一個(gè)部分而已拗慨。
理清楚這部分的關(guān)系后,再來看isa和superClass之間的關(guān)系赵抢。一個(gè)是指元類,另一個(gè)是指父類宠叼。兩個(gè)東西是兩個(gè)概念其爵。下面引用一張非常經(jīng)典的圖,用于理順實(shí)例摩渺,類,元類和父類之間的關(guān)系横侦。


實(shí)例、類瑞眼、元類棵逊、父類關(guān)系圖

Method

前面看完了類的定義,現(xiàn)在來看一下方法的定義辆影。

struct objc_method {
    SEL _Nonnull method_name          OBJC2_UNAVAILABLE;
    char * _Nullable method_types     OBJC2_UNAVAILABLE;
    IMP _Nonnull method_imp           OBJC2_UNAVAILABLE;
}

可以看出一個(gè)方法(method)包括3個(gè)部分蛙讥。SEL就是通過@selector()獲取到的數(shù)據(jù)結(jié)構(gòu),可以簡(jiǎn)單看成一個(gè)方法的名稱次慢。method_types就是參數(shù)和返回值的數(shù)據(jù)類型。IMP就是函數(shù)指針了劈愚。
IMP
函數(shù)指針很好理解闻妓,就是C語言的函數(shù)指針。定義為:

/// A pointer to the function of a method implementation. 
#if !OBJC_OLD_DISPATCH_PROTOTYPES
typedef void (*IMP)(void /* id, SEL, ... */ ); 
#else
typedef id _Nullable (*IMP)(id _Nonnull, SEL _Nonnull, ...); 
#endif

在使用IMP的時(shí)候由缆,可以直接像函數(shù)指針那樣去使用:

//1.獲取函數(shù)指針
IMP funcPoint = class_getMethodImplementation([self class], @selector(xxx));//"xxx"代表具體的方法名均唉,例如可以叫sayHelloWorld。
//2.使用函數(shù)指針
funcPoint(self,@selector(xxx)); //如果報(bào)錯(cuò)舔箭,則需要關(guān)閉Enable Strict Checking of objc_msgSendCalls。

關(guān)閉Xcode中的Enable Strict Checking of objc_msgSendCalls編譯選項(xiàng):

修改編譯選項(xiàng)

當(dāng)然也可以采用一些其他的手段來解決報(bào)錯(cuò)的問題靴庆,例如定義一個(gè)函數(shù)指針類型怒医,然后將獲得IMP進(jìn)行強(qiáng)制轉(zhuǎn)換。
method_types
method_types是一個(gè)char指針焰薄,是方法的參數(shù)和返回值類型組成的字串。以返回值開始塞茅,依次把參數(shù)拼接在一起。例如“i@”就表示返回值類型為int,參數(shù)類型為id描沟。每個(gè)類型對(duì)照什么樣的參數(shù)鞭光,具體可以參考Objective-C Runtime Programming Guide
SEL

/// An opaque type that represents a method selector.
typedef struct objc_selector *SEL;

在實(shí)際使用的過程中惰许,感覺selector完全就是承擔(dān)一個(gè)方法名稱的作用。

現(xiàn)在問題來了佩伤,SEL和IMP是什么關(guān)系晦毙?
方法調(diào)用的過程是從SEL尋找到IMP,然后再使用IMP執(zhí)行障斋。所以說SEL的作用僅僅只是用來尋找到IMP,真正進(jìn)行執(zhí)行的是IMP返敬。
那么為什么要SEL寥院?直接使用IMP不好秸谢?
直接使用IMP當(dāng)然可以泉瞻,并且C語言就只使用函數(shù)指針望侈。OC使用SEL其實(shí)就是為了能夠更好的實(shí)現(xiàn)一些語言的動(dòng)態(tài)性坦仍,例如方法交換(method swizzle)管跺。

總結(jié)

  1. 介紹了元類冷尉,并說明了元類和類的關(guān)系雀哨。
  2. 介紹了SEL和IMP。并說明了SEL和IMP的關(guān)系怜庸。

參考:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末嘉栓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子侵佃,更是在濱河造成了極大的恐慌,老刑警劉巖抚芦,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叉抡,死亡現(xiàn)場(chǎng)離奇詭異褥民,居然都是意外死亡洗搂,警方通過查閱死者的電腦和手機(jī)耘拇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門倡勇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來译隘,“玉大人,你說我怎么就攤上這事固耘√浚” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)路星。 經(jīng)常有香客問我洋丐,道長(zhǎng)友绝,這世上最難降的妖魔是什么肝劲? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任辞槐,我火速辦了婚禮催蝗,結(jié)果婚禮上育特,老公的妹妹穿的比我還像新娘缰冤。我一直安慰自己棉浸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布创倔。 她就那樣靜靜地躺著焚碌,像睡著了一般十电。 火紅的嫁衣襯著肌膚如雪鹃骂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音寝殴,去河邊找鬼杯矩。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的泌射。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼号显!你這毒婦竟也來了押蚤?” 一聲冷哼從身側(cè)響起羹应,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎劫灶,沒想到半個(gè)月后掖桦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體滞详,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蒲犬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年原叮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了巡蘸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片悦荒。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡境氢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情悦析,我是刑警寧澤强戴,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布酌泰,位于F島的核電站陵刹,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏也糊。R本人自食惡果不足惜羡宙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一狗热、第九天 我趴在偏房一處隱蔽的房頂上張望匿刮。 院中可真熱鬧,春花似錦、人聲如沸光羞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至勘纯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背堤结。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工唐责, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瘾带,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓朴恳,卻偏偏與公主長(zhǎng)得像于颖,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

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