isa指向關(guān)系
我們通過打印一個對象的類地址宇葱,發(fā)現(xiàn)一個真理:類對象只有一個瘦真!
LGPerson *p = [[LGPerson alloc] init];
p.name = @"Cooci";
p.age = 18;
Class class1= [LGPerson class];
Class class2= p.class;
Class class3= object_getClass(p);
NSLog(@"\n%p-\n%p-\n%p",class1,class2,class3);
其實實例對象、類對象黍瞧、元類诸尽、根元類、NSObject之前有這樣一種關(guān)系:
- 實例對象是由類對象初始化來的
- 類對象由元類初始化而來
- 元類是一種虛擬的類印颤,由系統(tǒng)幫我創(chuàng)建您机,不用手動創(chuàng)建
- 元類由根元類初始化而來
- 根元類由NSObject初始化而來
其實這里面就是isa的指針指向關(guān)系,上面的關(guān)系我們可以通過LLDB調(diào)試打印結(jié)果得來。
需要注意的是际看,isa是優(yōu)化過的咸产,說白了就是我們要尋找到isa,當我們讀取內(nèi)存對象的isa地址 & ISA_MASK 過后就是我們的isa執(zhí)行的對象地址了仲闽。
通過調(diào)試脑溢,可以證實我們的結(jié)論是正確的。
上面只驗證了對象赖欣,類屑彻,和元類的isa指向結(jié)果。另外顶吮,這里提供一個方法社牲,可以打印一個對象的元類,根元類的地址悴了,進行進一步驗證搏恤。
- (void)lgPrintClassRelationshipWithObject:(id)objc{
NSLog(@"*********************************************");
NSLog(@"\n實例對象地址 - %p",objc);
NSLog(@"\n類對象地址 - %p",[objc class]);
NSLog(@"\n父類對象地址 - %p",[objc superclass]);
NSLog(@"\n元類對象地址 - %p",object_getClass(objc));
NSLog(@"\n元類的父類對象地址 - %p",[object_getClass(objc) superclass]);
NSLog(@"\n根元類對象地址 - %p",object_getClass(object_getClass(objc)));
NSLog(@"\n根元類的父類對象地址 - %p",[object_getClass(object_getClass(objc)) superclass]);
NSLog(@"\n根根元類對象地址 - %p",object_getClass(object_getClass(object_getClass(objc))));
NSLog(@"\n根根元類的父類對象地址 - %p",[object_getClass(object_getClass(object_getClass(objc))) superclass]);
NSLog(@"*********************************************");
}
記住這張圖,ISA的指向流程让禀,一切都ok了挑社。
繼承關(guān)系
實例對象-->父類-->...-->NSObject-->nil
元類-->父類-->...-->根元類-->NSObject-->nil
下面這張圖的繼承關(guān)系是從上面經(jīng)典isa和superClass中分離出來的。