iOS OC對象的本質(zhì)窺探(對象分類)(二)

上面一篇文章講了OC對象的本質(zhì)豪硅,編譯成C++對象是以什么形式存儲的串纺,一個對象占多少內(nèi)存空間等問題丽旅,那么在OC語言里面,又分為幾種對象呢纺棺?其實(shí)平時的工作中通過[[NSObject alloc] init]這種形式創(chuàng)建的對象都是實(shí)例對象榄笙,另外還有兩類平時接觸甚少的對象,一個是類對象祷蝌,一個就是元類對象茅撞。

開篇引題 類對象分為三種:
實(shí)例對象
類對象
元類對象
這三中類型的對象之間是什么關(guān)系?每種類型的對象又有什么特點(diǎn)呢?

開始一探究竟
  • 實(shí)例對象
    實(shí)現(xiàn)以下代碼
NSObject *object1 = [[NSObject alloc] init];
NSObject *object2 = [[NSObject alloc] init];        
NSLog(@"%p %p",
              object1,
              object2);

打酉绯帷:0x100648340 0x100647440

總結(jié):不多講了鳞疲,第一篇文章已經(jīng)寫的很詳細(xì),
object1蠕蚜、object2是NSObject的instance對象(實(shí)例對象)
它們是不同的兩個對象尚洽,分別占據(jù)著兩塊不同的內(nèi)存
instance對象在內(nèi)存中存儲的信息包括
isa指針
其他成員變量

存儲的是各個成員變量的值,還有一個isa指針,一個類在內(nèi)存中的實(shí)例對象可以有多個靶累。

內(nèi)存存儲圖示


實(shí)例對象內(nèi)存存儲圖示.png
  • 類對象
    1.獲取類對象
    兩種方法
NSObject *object1 = [[NSObject alloc] init];
Class objectClass1 = [object1 class];

還可以通過一個runtime函數(shù)

NSObject *object1 = [[NSObject alloc] init];        
Class objectClass3 = object_getClass(object1);

object_getClass 函數(shù):傳入實(shí)例對象返回類對象腺毫,傳入類對象,返回元類對象
下面實(shí)現(xiàn)以下代碼

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];
        
NSLog(@"%p %p",
              object1,
              object2);
        
NSLog(@"%p %p %p %p %p",
              objectClass1,
              objectClass2,
              objectClass3,
              objectClass4,
              objectClass5);

打诱跫怼:0x100648340 0x100647440
     0x7fff9dab4118 0x7fff9dab4118 0x7fff9dab4118 0x7fff9dab4118 0x7fff9dab4118

會發(fā)現(xiàn)兩個實(shí)例對象的內(nèi)存地址是不一樣的潮酒,而通過兩個實(shí)例對象獲得的5個類對象的指針都是一樣的,說明邪蛔,一個類在內(nèi)存中只有一個類對象急黎。

總結(jié):
objectClass1 ~ objectClass5都是NSObject的class對象(類對象)
它們是同一個對象。每個類在內(nèi)存中有且只有一個class對象
class對象在內(nèi)存中存儲的信息主要包括
isa指針
superclass指針
類的屬性信息(@property)侧到、類的對象方法信息(instance method)
類的協(xié)議信息(protocol)勃教、類的成員變量信息(ivar)
......

內(nèi)存存儲圖示


類對象內(nèi)存存儲圖示.png
  • 元類對象
    執(zhí)行以下代碼獲取元類對象
// object_getClass  函數(shù):傳入實(shí)例對象返回類對象,傳入類對象匠抗,返回元類對象
Class objectClass3 = object_getClass([NSObject class]);

總結(jié):
objectMetaClass是NSObject的meta-class對象(元類對象)
每個類在內(nèi)存中有且只有一個meta-class對象
meta-class對象和class對象的內(nèi)存結(jié)構(gòu)是一樣的故源,但是用途不一樣,在內(nèi)存中存儲的信息主要包括
isa指針
superclass指針
類的類方法信息(class method)
......

元類對象內(nèi)存圖示.png

關(guān)于如何證明剛剛所總結(jié)的三種類型的對象分別存儲的什么信息汞贸,通過閱讀蘋果源碼可知

分析:實(shí)例對象绳军,類對象和元類對象中都有isa指針,而類對象和元類對象中除了含有isa指針之外還有superclass指針矢腻,問題:isa指針和superclass指針分別有什么作用呢门驾?

  • 分析 創(chuàng)建一個Person類給person類分別聲明一個對象方法和一個類方法
// Person
@interface Person : NSObject <NSCopying>
{
    @public
    int _age;
}
@property (nonatomic, assign) int no;
- (void)personInstanceMethod;
+ (void)personClassMethod;
@end

@implementation Person
- (void)personInstanceMethod{
}
+ (void)personClassMethod{
}
@end

// 調(diào)用 
Person *person = [[Person alloc] init];
[person personInstanceMethod];
[Person personClassMethod];
  • isa指針作用
    OC語言是消息機(jī)制 當(dāng)執(zhí)行[person personInstanceMethod]; 這行代碼時 實(shí)際會被編譯成 objc_msgSend(person, @selector(personInstanceMethod))進(jìn)行調(diào)用,那么剛剛說到實(shí)例對象中不存儲方法踏堡,那么當(dāng)調(diào)用時這個對象方法是怎么獲得的呢猎唁?
    答案: 當(dāng)實(shí)例對象調(diào)用對象方法時是通過isa指針,指向自己的類對象顷蟆,找到類對象中的方法信息诫隅,進(jìn)行調(diào)用。同理帐偎,當(dāng)執(zhí)行 [Person personClassMethod]; 這行代碼時逐纬,實(shí)例對象通過isa指針指向自己的類對象,又通過類對象中的isa指針指向元類對象削樊,獲取到類方法信息豁生。
    圖示:

    isa指針作用.png

  • 創(chuàng)建一個Person類給person類分別聲明一個對象方法和一個類方法,再創(chuàng)建一個繼承于Person類的Student類給Student類分別聲明一個對象方法和一個類方法

// Person
@interface Person : NSObject <NSCopying>
{
    @public
    int _age;
}
- (void)personInstanceMethod;
+ (void)personClassMethod;
@end

@implementation Person

- (void)personInstanceMethod
{
    
}
+ (void)personClassMethod
{
    
}
@end

// Student
@interface Student : Person <NSCoding>
{
@public
    int _weight;
}
- (void)studentInstanceMethod;
+ (void)studentClassMethod;
@end

@implementation MJStudent
- (void)studentInstanceMethod
{
    
}
+ (void)studentClassMethod
{
    
}
@end

// 調(diào)用
Student *student = [[Student alloc] init];
[student personInstanceMethod];
[Student personClassMethod];     
  • superclass指針作用
    總結(jié):當(dāng)執(zhí)行[student personInstanceMethod]這行代碼時 student對象通過isa指針找到自己類對象兔毒,結(jié)果發(fā)現(xiàn)類對象中沒有personInstanceMethod這個方法,然后利用superclass指針找到父類也就是Person的類對象甸箱,查看是否有 personInstanceMethod 方法信息育叁,如果有 就調(diào)用,沒有的話繼續(xù)向上查找芍殖。同理:當(dāng)執(zhí)行[Student personClassMethod]; 這行代碼時豪嗽,student對象通過isa指針找到自己類對象,又通過類對象的isa指針找到自己的元類對象結(jié)果發(fā)現(xiàn)元類對象中沒有personClassMethod這個方法豌骏,元類對象利用superclass指針向上逐級尋找父類的元類對象是否有此方法龟梦。直到NSobject停止,如果找到就調(diào)用窃躲,找不到就會奔潰 unrecognized selector sent to class 0x1000011a0'

圖示:


superclass指針作用.png

最后總結(jié):

instance -> 實(shí)例對象计贰,class -> 類對象,meta-class -> 元類對象

1.instance的isa指向class
2.class的isa指向meta-class
3.meta-class的isa指向基類的meta-class
4.class的superclass指向父類的class
5.如果沒有父類蒂窒,superclass指針為nil
6.meta-class的superclass指向父類的meta-class
7.基類的meta-class的superclass指向基類的class
8.instance調(diào)用對象方法的軌跡
9.isa找到class躁倒,方法不存在,就通過superclass找父類
10.class調(diào)用類方法的軌跡
11.isa找meta-class刘绣,方法不存在樱溉,就通過superclass找父類

圖示:


WeChataf27bd994cb5722150a32f853afae3b5.png
  • 畫一下[student personInstanceMethod]這行代碼的執(zhí)行順序


    [student personInstanceMethod]執(zhí)行順序.png
  • 畫一下[Student load]這行代碼的執(zhí)行順序


    [Student load]執(zhí)行順序.png

疑問?纬凤??類方法再調(diào)用時先去自己的元類對象中尋找撩嚼,如果沒有就去父類的元類對象中尋找停士,在沒有就去NSObject的元類對象中尋找,再就去NSObject的類對象中尋找(根據(jù)最上面的線可以看來)那是這么回事嗎完丽?下面來驗(yàn)證一下

//新建一個Car類恋技,繼承自NSObject
@interface Car : NSObject

@end

@implementation Car

@end

// 創(chuàng)建一個NSObject的類別
//.h中代碼
+ (void)test;
//.m中代碼
+ (void)test{
    NSLog(@"+[NSObject test] - %p", self);
}
//調(diào)用代碼
[Car test];

輸出 :[Car class] - 0x100001220

別的代碼都不變,將類別中.m中的代碼改成

//+號變成-號
- (void)test{
    NSLog(@"+[NSObject test] - %p", self);
}

輸出 :[Car class] - 0x100001220

再調(diào)用發(fā)現(xiàn)還是可以成功逻族,具體的原因吧蜻底,我也說的不是很好,就不誤導(dǎo)別人了聘鳞,如果有大神知曉薄辅,歡迎指正

如有疑問歡迎指正~

強(qiáng)烈推薦:
iOS OC對象的本質(zhì)窺探(一)
iOS獲取手機(jī)唯一標(biāo)示
iOS 高德地圖實(shí)現(xiàn)大頭針展示,分級大頭針抠璃,自定制大頭針站楚,在地圖上畫線,線和點(diǎn)共存搏嗡,路線規(guī)劃(駕車路線規(guī)劃)窿春,路線導(dǎo)航拉一,等一些常見的使用場景

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市旧乞,隨后出現(xiàn)的幾起案子蔚润,更是在濱河造成了極大的恐慌,老刑警劉巖尺栖,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抽碌,死亡現(xiàn)場離奇詭異,居然都是意外死亡决瞳,警方通過查閱死者的電腦和手機(jī)货徙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來皮胡,“玉大人痴颊,你說我怎么就攤上這事÷藕兀” “怎么了蠢棱?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長甩栈。 經(jīng)常有香客問我泻仙,道長,這世上最難降的妖魔是什么量没? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任玉转,我火速辦了婚禮,結(jié)果婚禮上殴蹄,老公的妹妹穿的比我還像新娘究抓。我一直安慰自己,他們只是感情好袭灯,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布刺下。 她就那樣靜靜地躺著,像睡著了一般稽荧。 火紅的嫁衣襯著肌膚如雪橘茉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天姨丈,我揣著相機(jī)與錄音畅卓,去河邊找鬼。 笑死构挤,一個胖子當(dāng)著我的面吹牛髓介,可吹牛的內(nèi)容都是我干的隔缀。 我是一名探鬼主播值纱,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了抢埋?” 一聲冷哼從身側(cè)響起筒饰,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤缓溅,失蹤者是張志新(化名)和其女友劉穎惠昔,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體豹绪,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡价淌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了瞒津。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蝉衣。...
    茶點(diǎn)故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖巷蚪,靈堂內(nèi)的尸體忽然破棺而出病毡,到底是詐尸還是另有隱情,我是刑警寧澤屁柏,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布啦膜,位于F島的核電站,受9級特大地震影響淌喻,放射性物質(zhì)發(fā)生泄漏僧家。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一裸删、第九天 我趴在偏房一處隱蔽的房頂上張望八拱。 院中可真熱鬧,春花似錦烁落、人聲如沸乘粒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至轧铁,卻和暖如春每聪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背齿风。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工药薯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人救斑。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓童本,卻偏偏與公主長得像,于是被迫代替她去往敵國和親脸候。 傳聞我的和親對象是個殘疾皇子穷娱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評論 2 354