Runtime學(xué)習(xí)筆記

備注:文章主要學(xué)習(xí)自飄飄白云的博客

Object & Class & Meta Class

objc中 class 與 object 的定義:

typedef struct objc_class *Class;
typedef struct objc_object {
    Class isa;
}   *id;

Class 是一個(gè) objc_class 結(jié)構(gòu)類(lèi)型的指針;而 id(任意對(duì)象) 是一個(gè) objc_object 結(jié)構(gòu)類(lèi)型的指針揍异,其第一個(gè)成員是一個(gè) objc_class 結(jié)構(gòu)類(lèi)型的指針仁堪。注意這里有一關(guān)鍵的引申解讀:內(nèi)存布局以一個(gè) objc_class 指針為開(kāi)始的所有東東都可以當(dāng)做一個(gè) object 來(lái)對(duì)待螃宙!

那 objc_class 又是怎樣一個(gè)結(jié)構(gòu)體呢?且看:

struct objc_class{
    struct objc_class* isa;
    struct objc_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;
    struct objc_protocol_list* protocols;
};

類(lèi)之間的關(guān)系

規(guī)則一:類(lèi)的實(shí)例對(duì)象的 isa 指向該類(lèi)坞靶;該類(lèi)的 isa 指向該類(lèi)的 metaclass;
規(guī)則二:類(lèi)的 super_class 指向其父類(lèi),如果該類(lèi)為根類(lèi)則值為 NULL娱节;
規(guī)則三:metaclass 的 isa 指向根 metaclass,如果該 metaclass 是根 metaclass 則指向自身祭示;
規(guī)則四:metaclass 的 super_class 指向父 metaclass肄满,如果該 metaclass 是根 metaclass 則指向該 metaclass 對(duì)應(yīng)的類(lèi);

無(wú)圖無(wú)真相!


那么 class 與 metaclass 有什么區(qū)別呢质涛?

class 是 instance object 的類(lèi)類(lèi)型稠歉。當(dāng)我們向?qū)嵗龑?duì)象發(fā)送消息(實(shí)例方法)時(shí),我們?cè)谠搶?shí)例對(duì)象的 class 結(jié)構(gòu)的 methodlists 中去查找響應(yīng)的函數(shù)汇陆,如果沒(méi)找到匹配的響應(yīng)函數(shù)則在該 class 的父類(lèi)中的 methodlists 去查找(查找鏈為上圖的中間那一排)怒炸。如下面的代碼中,向str 實(shí)例對(duì)象發(fā)送 lowercaseString 消息毡代,會(huì)在 NSString 類(lèi)結(jié)構(gòu)的 methodlists 中去查找 lowercaseString 的響應(yīng)函數(shù)横媚。

metaclass 是 class object 的類(lèi)類(lèi)型。當(dāng)我們向類(lèi)對(duì)象發(fā)送消息(類(lèi)方法)時(shí)月趟,我們?cè)谠擃?lèi)對(duì)象的 metaclass 結(jié)構(gòu)的 methodlists 中去查找響應(yīng)的函數(shù)灯蝴,如果沒(méi)有找到匹配的響應(yīng)函數(shù)則在該 metaclass 的父類(lèi)中的 methodlists 去查找(查找鏈為上圖的最右邊那一排)。如下面的代碼中孝宗,向 NSString 類(lèi)對(duì)象發(fā)送 stringWithString 消息穷躁,會(huì)在 NSString 的 metaclass 類(lèi)結(jié)構(gòu)的 methodlists 中去查找 stringWithString 的響應(yīng)函數(shù)。

練習(xí)

下面的代碼輸出什么?

@implementation Dog : Animal

- (instancetype)init{
    self = [super init];
    
    if (self) {
        NSLog(@"%@", NSStringFromClass([self class]));
        NSLog(@"%@", NSStringFromClass([super class]));
    }
    
    return self;
}

@end

runtime中- (Class)class方法實(shí)現(xiàn)如下

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

runtime中+ (Class)class方法實(shí)現(xiàn)如下

+ (Class)class {
    return self;
}

打印結(jié)果: 都輸出Dog

2016-06-22 21:11:22.451 RuntimeTest[969:29418] IMP: -[NSObject(Animal) run]
2016-06-22 21:11:22.452 RuntimeTest[969:29418] IMP: -[NSObject(Animal) run]

問(wèn): 為什么?

下面的代碼輸出什么?

BOOL res1 = [[NSObject class] isKindOfClass:[NSObject class]];
BOOL res2 = [[NSObject class] isMemberOfClass:[NSObject class]];

BOOL res3 = [[Animal class] isKindOfClass:[Animal class]];
BOOL res4 = [[Animal class] isMemberOfClass:[Animal class]];
        
Animal *animal = [[Animal alloc] init];
BOOL res5 = [animal class] == [Animal class];
BOOL res6 = [animal isKindOfClass:[Animal class]];
BOOL res7 = [animal isMemberOfClass:[Animal class]];
        
NSLog(@"%d %d %d %d %d %d %d", res1, res2, res3, res4, res5, res6, res7);

runtime中isKindOfClass實(shí)現(xiàn)如下

- (BOOL)isKindOf:aClass
{
    Class cls;
    for (cls = isa; cls; cls = cls->superclass) 
        if (cls == (Class)aClass)
            return YES;
    return NO;
}

isMemberOfClass實(shí)現(xiàn)如下

- (BOOL)isMemberOf:aClass
{
    return isa == (Class)aClass;
}

打印輸出:

2016-06-22 21:15:13.840 RuntimeTest[987:31071] 1 0 0 0 1 1 1

問(wèn): 為什么?

下面的代碼輸出什么

@interface NSObject (Animal)

+ (void)run;

@end

@implementation NSObject (Animal)

- (void)run
{
    NSLog(@"IMP: -[NSObject(Animal) run]");
}

@end

[NSObject run];
[[NSObject new] run];

打印輸出:

2016-06-22 21:19:31.619 RuntimeTest[997:33664] IMP: -[NSObject(Animal) run]
2016-06-22 21:19:31.620 RuntimeTest[997:33664] IMP: -[NSObject(Animal) run]

問(wèn):為什么?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末因妇,一起剝皮案震驚了整個(gè)濱河市问潭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌婚被,老刑警劉巖狡忙,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異址芯,居然都是意外死亡灾茁,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)谷炸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)北专,“玉大人,你說(shuō)我怎么就攤上這事旬陡⊥赝牵” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵描孟,是天一觀的道長(zhǎng)驶睦。 經(jīng)常有香客問(wèn)我砰左,道長(zhǎng),這世上最難降的妖魔是什么场航? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任缠导,我火速辦了婚禮,結(jié)果婚禮上旗闽,老公的妹妹穿的比我還像新娘。我一直安慰自己蜜另,他們只是感情好适室,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著举瑰,像睡著了一般捣辆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上此迅,一...
    開(kāi)封第一講書(shū)人閱讀 51,198評(píng)論 1 299
  • 那天汽畴,我揣著相機(jī)與錄音,去河邊找鬼耸序。 笑死忍些,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的坎怪。 我是一名探鬼主播罢坝,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼搅窿!你這毒婦竟也來(lái)了嘁酿?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤男应,失蹤者是張志新(化名)和其女友劉穎闹司,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體沐飘,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡游桩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了耐朴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片众弓。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖隔箍,靈堂內(nèi)的尸體忽然破棺而出谓娃,到底是詐尸還是另有隱情,我是刑警寧澤蜒滩,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布滨达,位于F島的核電站奶稠,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏捡遍。R本人自食惡果不足惜锌订,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望画株。 院中可真熱鬧辆飘,春花似錦、人聲如沸谓传。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)续挟。三九已至紧卒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間诗祸,已是汗流浹背跑芳。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留直颅,地道東北人博个。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像功偿,于是被迫代替她去往敵國(guó)和親坡倔。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354

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