OC對象的本質(zhì)

Objective-C

Objective-C是C語言的超集网梢,我們平時(shí)寫得OC震缭,底層的實(shí)現(xiàn)都是C\C++代碼,OC的對象战虏、類是基于C\C++的結(jié)構(gòu)體實(shí)現(xiàn)的拣宰。
可以使用以下命令行將OC代碼轉(zhuǎn)換為C\C++代碼(只能作為參考不一定百分百準(zhǔn)確)

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc <OC源文件> -o <輸出的.cpp文件>

如果需要鏈接其他框架,使用- framework參數(shù)烦感,比如-framework UIKit

NSObject

一般我們寫的對象都繼承于NSObject巡社,所以弄清楚NSObject相當(dāng)關(guān)鍵

  • NSObject底層實(shí)現(xiàn)相關(guān)源碼
struct NSObject_IMPL{
  Class *isa
}
//Class是objc_class結(jié)構(gòu)體指針
typedef objc_class *Class

NSObject類里只有Class isa指針,所以obj對象的地址值就是isa指針的地址值手趣。表面上看之只占用了8個(gè)字節(jié)(指針變量8個(gè)字節(jié))晌该,閱讀OC源碼可以看到實(shí)質(zhì)是分配了16個(gè)字節(jié)。
可以使用以下API查看內(nèi)存使用情況

//一個(gè)實(shí)例對象至少需要多少字節(jié)
class_getInstanceSize([NSObject class]);
//一個(gè)實(shí)例對象實(shí)際占用多少字節(jié)
malloc_size((__brige const void *)obj);

一個(gè)繼承NSObject的類的結(jié)構(gòu)體

//例如
@interface Person : NSObject
@property (nonatomic, assign) int age;
@end
struct Person_IMPL{
  stuct NSObject_IMPL NSObject_IVARS;
  int _age;
}
//NSObject_IMPL的成員變量只有isa指針一個(gè)绿渣,所以實(shí)際結(jié)構(gòu)體等價(jià)如下朝群,person實(shí)例對象的地址值還是isa指針的地址值,再繼承也同理
struct Person_IMPL{
  Class *isa;
  int _age;
}
OC對象分類

OC對象分為三類:instance對象(實(shí)例對象)中符、class對象(類對象)姜胖、meta-class對象(元類對象)

  • instance對象:通過類alloc出來的對象,每次alloc都會(huì)創(chuàng)建新的實(shí)例對象
NSObject *obj1 = [[NSObject alloc] init];
NSObject *obj2 = [[NSObject alloc] init];
//obj1淀散、obj2都是instance對象右莱,它們是不同的兩個(gè)對象蚜锨,分別占據(jù)著不同的內(nèi)存

instance對象在內(nèi)存中存儲(chǔ)的信息有isa指針和其他成員變量。

  • class對象(類對象)
NSObject *object1 = [[NSObject alloc] init];
NSObject *object2 = [[NSObject alloc] init];
Class objectClass1 = [object1 class];
Class objectClass2 = [object2 class];
Class objectClass3 = object_getClass(object1);
Class objectClass4 = object_getClass(object2);
Class objectClass5 = [NSObject class];

objectClass1 ~ objectClass5都是NSObject的class對象
它們都是同一個(gè)對象隧出,每一個(gè)類在內(nèi)存中有且只有一個(gè)class對象
class對象在內(nèi)存中存儲(chǔ)的信息主要包括:
isa指針
superclass指針
類的屬性信息(@property)踏志、類的對象方法信息(instance method)
類的協(xié)議信息(protocol)、類的成員變量信息(ivar)

  • meta-class(元類對象)
//獲取元類對象的方法
Class objMetaClass = object_getClass([NSObject class]);
/*
  注意:這個(gè)方法獲取到的還是類對象
  Class objMetaClass = [[NSObject class] class];
*/

objectMetaClass是NSObject的meta-class對象(元類對象)
每個(gè)類在內(nèi)存中有且只有一個(gè)meta-class對象
meta-class對象和class對象的內(nèi)存結(jié)構(gòu)是一樣的胀瞪,只是用途不一樣而已针余,在內(nèi)存中存儲(chǔ)的信息主要包括:
isa指針
superClass指針
類的類方法信息
......

  • Class的結(jié)構(gòu)
//struct objc_class 結(jié)構(gòu)
struct objc_class{
  Class isa;
  Class superclass;
  Cache_t cache;//方法緩存
  class_data_bit_t bit;//用于獲取類的具體信息
}
// bit & FAST_DATA_MASK 得到類的具體信息
struct class_rw_t {  // rw表示可讀寫
    uint32_t flags;
    uint32_t version;
    const class_ro_t *ro;
    method_array_t methods; //method_t 二維數(shù)組
    property_array_t properties; //屬性二維數(shù)組
    protocol_array_t protocols; //協(xié)議二維數(shù)組
    Class firstSubclass;
    Class nextSiblingClass;
    char *demangledName;
}
//struct class_ro_t 的結(jié)構(gòu)
struct class_ro_t { //ro表示只讀
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;
#ifdef __LP64__
    uint32_t reserved;
#endif
    const uint8_t * ivarLayout;
    const char * name; //類名
    method_list_t * baseMethodList; //方法列表
    protocol_list_t * baseProtocols; //協(xié)議列表
    const ivar_list_t * ivars; //成員變量列表
    const uint8_t * weakIvarLayout;
    property_list_t *baseProperties;
}
isa指針和supclass指針
  • instance的isa指針指向class
    instance調(diào)用對象方法時(shí),通過isa指針找到class凄诞,找出對應(yīng)的對象方法進(jìn)行調(diào)用
  • class的isa指針指向meta-class
    調(diào)用類方法時(shí)圆雁,通過class的isa找到meta-class,找出對應(yīng)的類方法進(jìn)行調(diào)用

從Arm64開始帆谍,優(yōu)化了isa指針伪朽,isa & ISA_MASK才是真正的地址值

  • class對象的superclass指針指向父類class對象
    當(dāng)instance調(diào)用父類對象方法時(shí),先通過isa指針找到class汛蝙,再通過class對象的superclass指針找到父類烈涮,然后再找出對應(yīng)對象方法進(jìn)行調(diào)用
  • meta-class對象的superclass指針指向父類的meta-class對象
    調(diào)用父類類方法時(shí),通過class的isa找到meta-class窖剑,再通過meta-class對象的superclass指針找到父類坚洽,然后再找出對應(yīng)的類方法進(jìn)行調(diào)用


    isa、superclass總結(jié)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末西土,一起剝皮案震驚了整個(gè)濱河市讶舰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌需了,老刑警劉巖跳昼,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異肋乍,居然都是意外死亡鹅颊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進(jìn)店門住拭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挪略,“玉大人,你說我怎么就攤上這事滔岳。” “怎么了挽牢?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵谱煤,是天一觀的道長。 經(jīng)常有香客問我禽拔,道長刘离,這世上最難降的妖魔是什么室叉? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮硫惕,結(jié)果婚禮上茧痕,老公的妹妹穿的比我還像新娘。我一直安慰自己恼除,他們只是感情好踪旷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著豁辉,像睡著了一般令野。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上徽级,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天气破,我揣著相機(jī)與錄音,去河邊找鬼餐抢。 笑死现使,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的旷痕。 我是一名探鬼主播碳锈,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼苦蒿!你這毒婦竟也來了殴胧?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤佩迟,失蹤者是張志新(化名)和其女友劉穎团滥,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體报强,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡灸姊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了秉溉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片力惯。...
    茶點(diǎn)故事閱讀 40,127評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖召嘶,靈堂內(nèi)的尸體忽然破棺而出父晶,到底是詐尸還是另有隱情,我是刑警寧澤弄跌,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布甲喝,位于F島的核電站,受9級(jí)特大地震影響铛只,放射性物質(zhì)發(fā)生泄漏埠胖。R本人自食惡果不足惜糠溜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望直撤。 院中可真熱鬧非竿,春花似錦、人聲如沸谋竖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽圈盔。三九已至豹芯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間驱敲,已是汗流浹背铁蹈。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留众眨,地道東北人握牧。 一個(gè)月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像娩梨,于是被迫代替她去往敵國和親沿腰。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評論 2 355

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