iOS runtime原理class isa

runtime class isa

所有繼承自 NSObject 的類實(shí)例化后的對(duì)象都會(huì)包含一個(gè)類型為 isa_t 的結(jié)構(gòu)體界轩。不只是實(shí)例會(huì)包含一個(gè) isa 結(jié)構(gòu)體彤蔽,所有的類也有這么一個(gè) isa

struct objc_object {
private:
isa_t isa;
...
}

最關(guān)鍵的就是isa_t這個(gè)類型和一系列的構(gòu)造函數(shù),點(diǎn)擊查看isa_t發(fā)現(xiàn)這是一個(gè)聯(lián)合體:


union isa_t 
{
    isa_t() { }
    isa_t(uintptr_t value) : bits(value) { }
    Class cls;
}

可以看到這個(gè)聯(lián)合體里面有個(gè)Class類型的屬性cls,看起來里面應(yīng)該是關(guān)于這個(gè)對(duì)象的類的相關(guān)信息,那我們?cè)倏纯碈lass包含了哪些內(nèi)容棉圈。

struct objc_class : objc_object {
    // Class ISA;
    Class superclass;
    cache_t cache;             // 方法緩存
    class_data_bits_t bits;    //bits 里面存放這當(dāng)前類屬性涩堤,方法眷蜓、協(xié)議等信息
    ...
}

由此可見Class是一個(gè)objc_class類型的結(jié)構(gòu)體,而objc_class繼承自objc_object胎围,說明類也是一個(gè)對(duì)象吁系,只是比普通的對(duì)象多了一些屬性,比如superclass等白魂。

  • 既然類也是一個(gè)objc_object汽纤,那就是說類也有一個(gè)isa指針,那類的isa指針指向哪里呢福荸?
    在class之上還有叫做元類(meta class)的存在蕴坪,而class的isa指針就是指向?qū)?yīng)的meta class,
    meta class的isa指向root meta class(絕大部分情況下是NSObject),root meta class的isa指針指向自己敬锐。

  • class中存儲(chǔ)的是描述對(duì)象的相關(guān)信息背传,那么相應(yīng)的meta class中存放的就是描述class相關(guān)信息。說的更直白一點(diǎn)台夺,在我們寫代碼時(shí)径玖,通過對(duì)象來調(diào)用的方法(實(shí)例方法)都是存儲(chǔ)在class中的,通過類名來調(diào)用的方法(類方法)都是存儲(chǔ)在meta class中的

  • 當(dāng)實(shí)例方法被調(diào)用時(shí)颤介,它要通過自己持有的 isa 來查找對(duì)應(yīng)的類梳星,然后在這里的 class_data_bits_t 結(jié)構(gòu)體中查找對(duì)應(yīng)方法的實(shí)現(xiàn)。同時(shí)滚朵,每一個(gè) objc_class 也有一個(gè)指向自己的父類的指針 super_class 用來查找繼承的方法冤灾。

實(shí)驗(yàn):

TestObject *testObj = [TestObject new];
NSLog(@"%d", [testObj class] == [TestObject class]);

這個(gè)log會(huì)輸出1(為true)

不好理解,看下具體源碼辕近,如下

+ (Class)class {
    return self;
}
- (Class)class {
    return object_getClass(self);
}

object_getClass方法最終返回的是isa瞳购。所以TestObject調(diào)用class方法,返回的是自身亏推;testObj調(diào)用class方法学赛,返回的是isa指向的類,也是TestObject吞杭。

舉一反三:

[self class] 與 [super class]

@implementation Son : Father
   - (id)init
   {
       self = [super init];
       if (self) {
           NSLog(@"%@", NSStringFromClass([self class]));
           NSLog(@"%@", NSStringFromClass([super class]));
       }
       return self;
   }
   @end

眼熟盏浇,在哪里見過你,是的芽狗,很多有筆試經(jīng)歷小伙伴會(huì)碰到這題绢掰,看似很簡(jiǎn)單,但是被問為什么的時(shí)候?這么簡(jiǎn)單滴劲,居然問為什么攻晒,當(dāng)時(shí)還是太嫩了,還是太年輕了班挖。

詳解:

NSStringFromClass([self class]) = Son
NSStringFromClass([super class]) = Son

self 是類的隱藏參數(shù)鲁捏,指向當(dāng)前調(diào)用方法的這個(gè)類的實(shí)例;
super 本質(zhì)是一個(gè)編譯器標(biāo)示符萧芙,和 self 是指向的同一個(gè)消息接受者给梅。不同點(diǎn)在于:super 會(huì)告訴編譯器,當(dāng)調(diào)用方法時(shí)双揪,去調(diào)用父類的方法动羽,而不是本類中的方法。

當(dāng)使用 self 調(diào)用方法時(shí)渔期,會(huì)從當(dāng)前類的方法列表中開始找运吓,如果沒有,就從父類中再找疯趟;而當(dāng)使用 super 時(shí)拘哨,則從父類的方法列表中開始找。然后調(diào)用父類的這個(gè)方法迅办。

在調(diào)用[super class]的時(shí)候宅静,runtime會(huì)去調(diào)用objc_msgSendSuper方法,而不是objc_msgSend站欺;

OBJC_EXPORT void objc_msgSendSuper(void /* struct objc_super *super, SEL op, ... */ )

/// Specifies the superclass of an instance. 
struct objc_super {
    /// Specifies an instance of a class.
    __unsafe_unretained id receiver;

    /// Specifies the particular superclass of the instance to message. 
#if !defined(__cplusplus)  &&  !__OBJC2__
    /* For compatibility with old objc-runtime.h header */
    __unsafe_unretained Class class;
#else
    __unsafe_unretained Class super_class;
#endif
    /* super_class is the first class to search */
};

在objc_msgSendSuper方法中姨夹,第一個(gè)參數(shù)是一個(gè)objc_super的結(jié)構(gòu)體,這個(gè)結(jié)構(gòu)體里面有兩個(gè)變量矾策,一個(gè)是接收消息的receiver磷账,一個(gè)是當(dāng)前類的父類super_class。

objc_msgSendSuper的工作原理應(yīng)該是這樣的:
從objc_super結(jié)構(gòu)體指向的superClass父類的方法列表開始查找selector贾虽,找到后以objc->receiver去調(diào)用父類的這個(gè)selector逃糟。注意,最后的調(diào)用者是objc->receiver蓬豁,而不是super_class绰咽!

那么objc_msgSendSuper最后就轉(zhuǎn)變成:

// 注意這里是從父類開始msgSend,而不是從本類開始
objc_msgSend(objc_super->receiver, @selector(class))

/// Specifies an instance of a class.  這是類的一個(gè)實(shí)例
    __unsafe_unretained id receiver;   


// 由于是實(shí)例調(diào)用地粪,所以是減號(hào)方法
- (Class)class {
    return object_getClass(self);
}
這里 其實(shí)就是 [self class] == [Son class] ,又回到之前講過的isa知識(shí)了

由于找到了父類NSObject里面的class方法的IMP(一個(gè)函數(shù)指針,保存了方法的地址)取募,又因?yàn)閭魅氲娜雲(yún)bjc_super->receiver = self。self就是son蟆技,調(diào)用class玩敏,所以父類的方法class執(zhí)行IMP之后斗忌,輸出還是son,最后輸出兩個(gè)都一樣旺聚,都是輸出son织阳。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市砰粹,隨后出現(xiàn)的幾起案子唧躲,更是在濱河造成了極大的恐慌,老刑警劉巖伸眶,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惊窖,死亡現(xiàn)場(chǎng)離奇詭異刽宪,居然都是意外死亡厘贼,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門圣拄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嘴秸,“玉大人,你說我怎么就攤上這事庇谆≡榔” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵饭耳,是天一觀的道長(zhǎng)串述。 經(jīng)常有香客問我,道長(zhǎng)寞肖,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮抡草,結(jié)果婚禮上怔揩,老公的妹妹穿的比我還像新娘。我一直安慰自己琼稻,他們只是感情好吮螺,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著帕翻,像睡著了一般鸠补。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嘀掸,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天紫岩,我揣著相機(jī)與錄音,去河邊找鬼横殴。 笑死被因,一個(gè)胖子當(dāng)著我的面吹牛卿拴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播梨与,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼堕花,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了粥鞋?” 一聲冷哼從身側(cè)響起缘挽,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎呻粹,沒想到半個(gè)月后壕曼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡等浊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年腮郊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片筹燕。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡轧飞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出撒踪,到底是詐尸還是另有隱情过咬,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布制妄,位于F島的核電站掸绞,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏耕捞。R本人自食惡果不足惜衔掸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望砸脊。 院中可真熱鬧具篇,春花似錦、人聲如沸凌埂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)瞳抓。三九已至埃疫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間孩哑,已是汗流浹背栓霜。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留横蜒,地道東北人胳蛮。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓销凑,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親仅炊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子斗幼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

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

  • 本文轉(zhuǎn)載自:http://yulingtianxia.com/blog/2014/11/05/objective-...
    ant_flex閱讀 749評(píng)論 0 1
  • 出題者簡(jiǎn)介: 孫源(sunnyxx),目前就職于百度抚垄,負(fù)責(zé)百度知道 iOS 客戶端的開發(fā)工作蜕窿,對(duì)技術(shù)喜歡刨根問底和...
    戈多_于勒閱讀 1,790評(píng)論 0 5
  • 我們常常會(huì)聽說 Objective-C 是一門動(dòng)態(tài)語(yǔ)言,那么這個(gè)「動(dòng)態(tài)」表現(xiàn)在哪呢呆馁?我想最主要的表現(xiàn)就是 Obje...
    Ethan_Struggle閱讀 2,182評(píng)論 0 7
  • 天桐经, 煙雨蒙蒙載客還。 東風(fēng)去浙滤, 來飲舊時(shí)歡阴挣。 ——樂詩(shī)歡夢(mèng)
    T缺月掛疏桐閱讀 281評(píng)論 0 1
  • 這次期中考試雖然進(jìn)步了屯吊,但考的還是很差送巡。很多理想的科目也考得不高摹菠。有的還因?yàn)樽鲱}慢失了很多分。副科也拉了很多分骗爆。尤...
    不知道該取什么名字好_5bef閱讀 203評(píng)論 0 0