開始探究
本篇開始正式研究類和isa许布,歸根結(jié)底還是圍繞類
展開探索吧彪。研究類其實無非就是研究isa的走位
和類的繼承關系
這兩個,下面??我們就從isa走位開始進入正題。
本文收錄:<掘金>S_H:isa&類結(jié)構(gòu)探究
準備工作
我們要研究類替蔬,所以首先肯定要需要定義幾個類,這里我們就定義兩個類屎暇,并且他們之間最好有繼承關系承桥,方便后續(xù)探索。
- 繼承自NSObject的YSHPerson類
- 繼承自YSHPerson的YSHStudent類
- 在main.m文件中定義兩個對象
元類
什么是元類
根悼?
- 以類作為其實例的類凶异。
- 元類的定義和創(chuàng)建都是由編譯器完成的。
- 對象的isa指向類挤巡,而類其實也是一個對象剩彬,我們可以稱之為類對象,而類對象的isa則指向了元類矿卑。
這么看元類的定義太抽象了喉恋,下面我通過lldb結(jié)合代碼進行分析。
isa走位
由上圖分析母廷,我們大致可以得出isa的走位:
-
對象的isa
指向類
-
類的isa
指向元類
-
元類的isa
指向根元類(NSObject)
-
根元類的isa
指向自己
繼承
下面我們來分析一下繼承關系轻黑,我們分為兩種:
- 類的繼承關系
我們先寫一個函數(shù),通過信息打印分析一下琴昆。
通過??的打印信息氓鄙,我們可以看出類的繼承關系:
子類
---->父類
---->父類的父類
---->根類(NSObject)
---->nil
2. 元類的繼承關系
剛才我們分析了類的繼承關系,那我們大膽猜測元類是否也有相應的集成關系呢业舍?
老規(guī)矩抖拦,我們還是先寫一個函數(shù),通過信息打印來更加直觀的分析舷暮。
通過??的打印信息蟋座,我們可以看出來元類之間也是存在繼承關系的,但是元類的繼承鏈路和類的繼承鏈路還是有不同的脚牍。特殊
之處在根元類(NSObject)最后又繼承了根類(NSObject)
子元類
---->父元類
---->父元類的父元類
---->根元類(NSObject)
---->根類(NSObject)
---->nil
isa走位&類繼承總結(jié)
根據(jù)上面的探索分析,我們可以得出來那一份肥腸經(jīng)典的isa&繼承走位圖
isa走位
-
實例對象
(instance of subclass)的isa
指向類
(class)巢墅。 -
類對象
(class)isa
指向元類
(meta class)诸狭。 -
元類
(meta class)的isa
指向根元類(NSObject)
(root metal class)券膀。 -
根元類(NSObject)
(root meta class)的isa
指向自己本身,形成閉環(huán)驯遇。
繼承關系
- 類的繼承
-
類
(subClass)繼承自父類
(superClass)芹彬。 -
父類
(superClass)繼承自根類(NSObject)
(rootClass)。 -
根類(NSObject)
繼承自nil
叉庐,這也是為什么NSObject是根類舒帮。
- 元類的繼承
-
子類的元類
(metal subClass)繼承自父類的元類
(metal superClass)。 -
父類的元類
(metal superClass)繼承自根元類
(root metal class)陡叠。 -
根元類
(root metal class)繼承自根類(NSObject)
(root class)玩郊。
特別注意!M髡蟆R牒臁!兴溜!
不是說OC沒有繼承關系
嗎侦厚?此處說的繼承關系是對象的繼承關系
,而非類
拙徽。類是有繼承關系的刨沦。
當然還有哪些不明白的歡迎加入iOS交流群!
類的結(jié)構(gòu)分析
內(nèi)存偏移
分析類的結(jié)構(gòu)之前膘怕,我們需要了解內(nèi)存偏移想诅,因為我們想要拿到類的內(nèi)容時,需要通過內(nèi)存偏移去取淳蔼。
- 普通指針
a和b都指向10侧蘸,但是a和b的地址不一樣,地址之間相差4字節(jié)鹉梨,因為a和b都是int類型讳癌。
- 對象指針
p1和p2也是
指針
,分別指向[YSHPerson alloc]創(chuàng)建的內(nèi)存地址
存皂。
&p1和&p2是指向p1和p2對象指針的地址
晌坤。
- 數(shù)組指針
①
&c
和&c[0]
取出來的都是首地址。
②&c
和&c[1]
相差4個字節(jié)(地址之間差值旦袋,取決于存儲的數(shù)據(jù)類型)
③通過首地址+偏移量
可以取出數(shù)組中的元素骤菠,偏移量也就是我們常說的數(shù)組下標。
內(nèi)存中首地址移動的字節(jié)數(shù) = 偏移量 * 數(shù)據(jù)類型字節(jié)數(shù)
類結(jié)構(gòu)探索
通過objc源碼疤孕,我們可以大致知道objc_class內(nèi)部大致有哪些東西商乎,如下圖所示:
①
isa
:雖然此處注釋了鲜戒,但是objc_class繼承自objc_object,所以objc_class肯定也是有isa的抹凳,占8字節(jié)遏餐。
②superclass
:Class類型,本質(zhì)是一個結(jié)構(gòu)體指針赢底,占8字節(jié)失都。
③cache
:是cache_t
類型,通過源碼我們可以知道cache_t是結(jié)構(gòu)體類型
幸冻,結(jié)構(gòu)體類型的內(nèi)存大小是由其內(nèi)部的屬性來決定的粹庞。
④bits
:是class_data_bits_t
類型,我們無法獲取其具體內(nèi)存大小嘁扼,只能通過我們上面說的內(nèi)存偏移去獲取bits信粮。
- cache內(nèi)存大小計算
我們發(fā)現(xiàn)cache_t是一個結(jié)構(gòu)體,除去static修飾的屬性趁啸,其中影響其內(nèi)存大小的只有??截圖中的兩個:_bucketsAndMaybeMask
和聯(lián)合體
我們可以得出cache_t
這個結(jié)構(gòu)體的內(nèi)存大小為8+8=16字節(jié)
强缘。
- 獲取bits
在通過內(nèi)存偏移獲取bits內(nèi)容前,我們先看下源碼不傅。
我們底層探索的思路就是:大膽猜測旅掂、小心驗證!!!
我們在源碼中發(fā)現(xiàn)了一個很有意思的結(jié)構(gòu)體class_rw_t
,這里面有幾個我們非常熟悉的屬性method_array_t
property_array_t
property_array_t
访娶,不管三七二十一商虐,我先認為屬性、方法存在這里面崖疤,下面??我們正式開始驗證這個大膽的猜測秘车。
- 屬性列表-property_list
我們首先從屬性列表開始探索,具體分析如下圖所示:
我們發(fā)現(xiàn)property_list里只有屬性
劫哼,沒有成員變量
叮趴。那么成員變量又會存在哪里呢?下面我們一步一步探索权烧。
PS:屬性與成員變量的區(qū)別就是有沒有set/get方法
眯亦,如果有,則是屬性般码;如果沒有妻率,則是成員變量。
- 方法列表-methods_list
探索方法列表的方式同屬性列表板祝,lldb具體步驟如下圖所示:
我們會發(fā)現(xiàn)在方法列表里只有實例方法
和屬性的set/get方法
宫静,并沒有類方法
- 成員變量-ivars
剛才分析屬性列表時,我們遺留了一個問題,property_list
中只有屬性
囊嘉,那么成員變量存在哪里了呢温技? 通過查看class_rw_t的源碼發(fā)現(xiàn),其中除了methods扭粱、properties、protocols震檩,還有一個ro
琢蛤,通過查看class_ro_t
源碼,我們發(fā)現(xiàn)其有一個ivar_list_t
類型的ivars
屬性抛虏。
我們再次做次做出大膽猜測:成員變量
是否存儲
在這個ivar_list_t類型的ivars
屬性中呢博其?下面我們就繼續(xù)小心驗證。
下面??就是lldb步驟:
我們獲取的ivars屬性迂猴,通過打印發(fā)現(xiàn) 成員列表中除了sex
慕淡,還有_name
和_familyName
。
屬性&成員變量總結(jié)
- 通過@property聲明的
屬性
沸毁,存儲在類的bits-->data()-->properties()-->list
峰髓,只包含
屬性- 通過{}聲明的
成員變量
,存儲在類的bits-->data()-->ro()-->ivars
中息尺,除了成員變量携兵,還包括屬性定義的_成員變量
- 類方法
剛才我們分析methods_list時,也遺留了一個問題搂誉,發(fā)現(xiàn)類的methods里只有實例方法徐紧,并沒有類方法,那么類方法又是存儲在哪里呢炭懊?
在最開始我們分析isa走位的時候并级,提到了元類
的概念,元類是用來存儲類的信息的
侮腹。 那么我們就又可以大膽猜測了:類方法是否就是存儲在元類的methods_list里呢嘲碧?
下面??是我們進行l(wèi)ldb驗證的步驟:
經(jīng)過我們的層層驗證,發(fā)現(xiàn)我們大膽的猜測都是正確的?Q教丁!??????
實例方法&類方法總結(jié)
類的實例方法存儲在
bits-->data()-->methods()-->list
至非,其中既包括實例方法
钠署,還包括屬性的set/get方法
。類的類方法存儲在
元類bits-->data()-->methods()-->list
荒椭,其中只有類方法
谐鼎。
總結(jié)
學習其實就是一個探索的過程中,在實操中一步一步驗證我們的大膽猜測趣惠,這樣的學習方法只有一個壞處狸棍,那就是提升我們對知識的理解程度和加深對知識掌握的印象身害。
文末推薦:iOS熱門文集&視頻解析
① Swift
② iOS底層技術
③ iOS逆向防護
④ iOS面試合集
⑤ 大廠面試題+底層技術+逆向安防+Swift
喜歡的小伙伴記得點贊喔~
收藏等于白嫖,點贊才是真情?( ′???` )?