01isa
三種對象在內(nèi)存中的結構,他們之間肯定是有聯(lián)系的
我們在調(diào)用方法的時候本質(zhì)上是發(fā)消息漆腌,給這個對象發(fā)消息槐沼。而對象方法存在類對象中,類方法存在元類對象中润绵,所以他們之間使用了isa來進行連接
instance的isa指向class
當調(diào)用對象方法時线椰,通過instance的isa找到class,最后找到對象方法的實現(xiàn)進行調(diào)用class的isa指向meta-class
當調(diào)用類方法時尘盼,通過class的isa找到meta-class憨愉,最后找到類方法的實現(xiàn)進行調(diào)用
02-class的superclass
很重要牽扯到方法調(diào)用,是用來找父類的卿捎,
我們首先創(chuàng)建兩個類Person 和Student配紫,讓他們之間繼承,加上NSObject一共會有3個類對象午阵,
@interface Person:NSObject
@end
@interface Student:Person //16
@end
他們之間的關系
當Student的instance對象要調(diào)用Person的對象方法時躺孝,會先通過isa找到Student的class,然后通過superclass找到Person的class底桂,最后找到對象方法的實現(xiàn)進行調(diào)用
03-meta-class的superclass
元類的superclass之間的關系和作用植袍,Student的元類的superclass指針指向的是Person的元類對象,Person的元類的superclass指針指向的是NSObject的元類對象
當Student的class要調(diào)用Person的類方法時戚啥,會先通過isa找到Student的meta-class奋单,然后通過superclass找到Person的meta-class,最后找到類方法的實現(xiàn)進行調(diào)用
04-總結01.
instance的isa指向class
class的isa指向meta-class
meta-class的isa指向基類的meta-class
class的superclass指向父類的class
如果沒有父類猫十,superclass指針為nil
meta-class的superclass指向父類的meta-class
基類的meta-class的superclass指向基類的class
instance調(diào)用對象方法的軌跡
isa找到class览濒,方法不存在,就通過superclass找父類class調(diào)用類方法的軌跡
isa找meta-class拖云,方法不存在贷笛,就通過superclass找父類,如果找到基類的元類也沒有宙项,他回去基類的類對象里面找這個方法乏苦,如果還是沒有,就會報錯unrecognized selector sent to
05總結02
如果自己的類對象和父類的類對象里面都有test方法尤筐,他會先調(diào)用自己類的方法汇荐,如果自己的類沒有就會調(diào)用父類的方法,如果父類也沒有這個類方法盆繁,但是有對象方法掀淘,那么它也可以調(diào)用成功,因為方法的調(diào)用本質(zhì)就是發(fā)消息objc_senMessage(接受者油昂,@selector(name));他只關心給誰發(fā)送了哪條消息革娄,并不在乎是-或者+開頭的方法
06isa細節(jié)
對象isa里面存的地址值就是他所指向的對象的地址倾贰,從64bit開始 isa需要進行一次位運算,才能計算出真實地址
# if __arm64__
# define ISA_MASK 0x0000000ffffffff8ULL
# elif __x86_64__
# define ISA_MASK 0x00007ffffffffff8ULL
# else
# error unknown architecture for packed isa
# endif
如果我們想要看一下person的isa的值拦惋, 可以利用lldb調(diào)試工具操作匆浙,經(jīng)過我們自己手動進行isa之間的位運算,法相厕妖,person的isa&isa_mask之后確實得到的就是Person類對象的地址(isa的地址)
如果我們想要拿出類對象的isa指針首尼,需要將這個類轉(zhuǎn)成我們自制設計的結構體,因為原來不允許我們訪問言秸,所以根據(jù)我們計算饰恕,類對象和元類的isa也是對應的
superclass這個指針是不是存在mask運算的,直接可以找到父類類對象的地址
07class和metaClass的結構
證明類對象里面確實存放了屬性信息井仰,對象方法信息埋嵌,協(xié)議信息
因為類對象都是一種objc_class類型的結構,所以這個結構體里面的信息俱恶,就說我們類對象在內(nèi)存中存放的信息雹嗦,通過我們下載的開源的源碼,搜索objc_class找到新的結構體合是,在objc-runtime-new里面,這個里面的結構體也有繼承了罪,因為他是c++的結構體,他和類沒有區(qū)別,class對象和meta-class對象本質(zhì)上都是struct objc_class類型
struct objc_class : objc_object {
// Class ISA;
Class superclass;
cache_t cache; // formerly cache pointer and vtable
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
class_rw_t *data() const {
return bits.data();
}
}
//class_rw_t rw=readwrite t=table
struct objc_class的結構大致為一下內(nèi)容
如果我們想驗證一下是否真的是在內(nèi)存中的結構聪全,我們可以自己模仿他的結構體寫一個我們自己的泊藕,然后把他們的類對象轉(zhuǎn)成我們自己的結構體進一步驗證。
但是如果弄成一樣的太耗時間难礼,而且可能編譯不通過娃圆,所以我們手動改了一些地方;如果我們想編譯c++的文件蛾茉,我們需要把文件后綴改成.mm讼呢。c++的結構體可以不帶struct直接使用
對象的isa指針指向哪里?
instance對象的isa指向class對象
class對象的isa指向meta-class對象
meta-class對象的isa指向基類的meta-class對象
OC的類信息存放在哪里谦炬?
對象方法悦屏、屬性、成員變量键思、協(xié)議信息础爬,存放在class對象中
類方法,存放在meta-class對象中
成員變量的具體值吼鳞,存放在instance對象
8 答疑
類對象和元類對象一直在內(nèi)存中看蚜,知道程序結束才釋放內(nèi)存,當程序一啟動就分配了內(nèi)存赖条。
實例對象里面的成員變量是具體的值失乾,類對象里面的成員變量,是成員變量的信息纬乍。