本文源自本人的學(xué)習(xí)記錄整理與理解滤奈,其中參考閱讀了部分優(yōu)秀的博客和書籍,盡量以通俗簡(jiǎn)單的語(yǔ)句轉(zhuǎn)述撩满。引用到的地方如有遺漏或未能一一列舉原文出處還望見(jiàn)諒與指出蜒程,另文章內(nèi)容如有不妥之處還望指教,萬(wàn)分感謝伺帘。
1. 一個(gè)NSObject對(duì)象占用多少內(nèi)存 昭躺?
答:系統(tǒng)分配了16個(gè)字節(jié)給NSObject對(duì)象(通過(guò)malloc_size函數(shù)獲得),但NSObject對(duì)象內(nèi)部值使用了8個(gè)字節(jié)的空間(64位環(huán)境下伪嫁,可以通過(guò)class_getInstenceSize函數(shù)獲得)
2. 如果一個(gè)實(shí)例對(duì)象有自定義成員變量或?qū)傩郧涎觯挥只蛘哂懈割悾挥只蛘哂凶远x方法礼殊、協(xié)議驹吮;這個(gè)時(shí)候占多大內(nèi)存空間呢 针史?
這其中涉及到了結(jié)構(gòu)體成員變量的內(nèi)存對(duì)齊的問(wèn)題,結(jié)構(gòu)體內(nèi)存對(duì)齊其中有一條要求結(jié)構(gòu)體大小需要是最大成員變量大小的整數(shù)倍碟狞,而最大成員變量是指針變量(8個(gè)字節(jié))啄枕,結(jié)構(gòu)體的最終的大小需要是8的整數(shù)倍。系統(tǒng)實(shí)際分配的大小也是16字節(jié)族沃,所以分配的內(nèi)存會(huì)是16的整數(shù)倍频祝。詳細(xì)了解可以參考iOS底層原理(一):OC對(duì)象實(shí)際占用內(nèi)存與開(kāi)辟內(nèi)存關(guān)系。至于自定義方法脆淹、協(xié)議是不存儲(chǔ)在實(shí)例對(duì)象的內(nèi)存中的常空,而是放在類對(duì)象的方法列表中。(原因是方法只需要存儲(chǔ)一次就可以了盖溺,不管初始化多少個(gè)實(shí)例對(duì)象漓糙,但只要都是同一個(gè)類初始化出來(lái)的都需要相同的方法,這樣看來(lái)放在類對(duì)象存儲(chǔ)是很合理的)烘嘱。
注意
不同的數(shù)據(jù)類型所分配的內(nèi)存大小是不同的昆禽,比如一個(gè)指針?lè)峙涞目臻g是8個(gè)字節(jié),一個(gè)基本數(shù)據(jù)類型分配的空間是4個(gè)字節(jié)蝇庭。下面提供一張一覽表:
3. 對(duì)象isa指針指向哪里醉鳖?
? <1> instance(實(shí)例)對(duì)象的isa指向其class對(duì)象;
? <2> class對(duì)象的isa指針指向meta-class(元類)對(duì)象
? <3> meta-class(元類)對(duì)象的isa指針指向基類(一般是指NSObject)的meta-class對(duì)象
但是被KVO監(jiān)聽(tīng)的對(duì)象除外哮内,因?yàn)镵VO監(jiān)聽(tīng)會(huì)在運(yùn)行時(shí)生成新的派生類盗棵。isa指針指向的是這個(gè)派生類。
4 . isa 指針變量中存儲(chǔ)了什么 北发?superclass呢 漾根?
在arm64架構(gòu)之前,存儲(chǔ)了ISA指針指向?qū)ο蟮膬?nèi)存地址鲫竞,但是在arm64之后需要在存儲(chǔ)地址值加上ISA_MASK 這個(gè)值才是指向?qū)ο蟮膬?nèi)存地址。示意圖如下
跟isa不同逼蒙,superclass指針是直接指向父類的類對(duì)象从绘,superclass指針中存儲(chǔ)的內(nèi)容就是父類的類對(duì)象的地址值。
5. 為什么幾乎所有的實(shí)例對(duì)象都有一個(gè)isa指針 是牢?
簡(jiǎn)單回答:OC 實(shí)例對(duì)象基本上都繼承自NSObject,而NSObject自帶就有一個(gè)成員變量isa . 所以實(shí)例對(duì)象基本上都有這個(gè)isa 指針僵井。
有深度的回答:OC 實(shí)例對(duì)象基本上都繼承自NSObject,而NSObject自帶就有一個(gè)成員變量isa . 另外isa是用來(lái)指向?qū)嵗龑?duì)象的類對(duì)象、類對(duì)象的元類對(duì)象的驳棱,通過(guò)isa可以找到相關(guān)的方法批什、協(xié)議進(jìn)行調(diào)用,這在OC運(yùn)行時(shí)通過(guò)object_getClass()方法社搅,傳入對(duì)象的isa指針來(lái)查找對(duì)象(查找實(shí)例對(duì)象的類對(duì)象驻债,查找類對(duì)象的元類對(duì)象乳规,查找元類對(duì)象返回基類的元類對(duì)象)。都需要用到的一個(gè)重要的指針變量合呐,所以所有繼承自NSObject的實(shí)例對(duì)象都有一個(gè)isa指針變量暮的。
總結(jié):
?1.Class objc_getClass(const char *aClassName)
?1> 傳入字符串類名
?2> 返回對(duì)應(yīng)的類對(duì)象
?2.Class object_getClass(id obj)
?1> 傳入的obj可能是instance對(duì)象、class對(duì)象淌实、meta-class對(duì)象
?2> 返回值
?a) 如果是instance對(duì)象冻辩,返回class對(duì)象
?b) 如果是class對(duì)象,返回meta-class對(duì)象
?c) 如果是meta-class對(duì)象拆祈,返回NSObject(基類)的meta-class對(duì)象
?3.- (Class)class恨闪、+ (Class)class
?1> 返回的就是類對(duì)象
?- (Class)class { return self->isa;}
?+ (Class)class { return self; }
6. isa 指針是否絕對(duì)安全 ?
? ?isa 指針不是絕對(duì)安全的放坏。
原因:isa指針是用來(lái)查找實(shí)例對(duì)象的類對(duì)象咙咽,類對(duì)象的元類對(duì)象;如果在運(yùn)行時(shí)修改其isa指針指向一個(gè)不相關(guān)的類或元類此時(shí)就不在安全
7. OC 對(duì)象的信息存放哪里 轻姿?
? ?<1> 成員變量的具體值存放在實(shí)例(instance)對(duì)象中.
??<2> 對(duì)象方法犁珠、屬性、成員變量互亮、協(xié)議信息都是存放在類(class)對(duì)象中的.
? ?<3> 類方法存放在元類(meta-class)對(duì)象中.
8. 一個(gè)實(shí)例對(duì)象調(diào)用copy方法犁享,返回的是同一對(duì)象嗎 ?
可能是同一個(gè)對(duì)象也可能不是,這取決與被拷貝的對(duì)象是什么類型豹休;如對(duì)可變數(shù)組拷貝炊昆,生成不可變數(shù)組,這時(shí)很明顯生成了新的對(duì)象是深拷貝當(dāng)然就不是同一個(gè)對(duì)象威根!再或者某個(gè)對(duì)象實(shí)現(xiàn)了copyWithZone方法并且返回了通過(guò)alloc凤巨、new方法創(chuàng)建的對(duì)象那也是不同對(duì)象!
9. OC 對(duì)象內(nèi)存分配的注意點(diǎn)或特點(diǎn)是什么 洛搀?
OC對(duì)象的本質(zhì)是結(jié)構(gòu)體敢茁,結(jié)構(gòu)體在分配內(nèi)存時(shí)是以16個(gè)字節(jié)為單位在堆空間分配存儲(chǔ)空間的;在這個(gè)過(guò)程中是以內(nèi)存對(duì)齊為原則進(jìn)行內(nèi)分配留美。
比如一個(gè)實(shí)例對(duì)象的成員變量總共需要28字節(jié)的存儲(chǔ)空間那么系統(tǒng)就會(huì)分配32個(gè)字節(jié)的內(nèi)存給它彰檬。