OC中對象的分類:
1.實例對象:instance object;
2.類對象:class object;
3.元類對象:meta class object;
實例對象的創建和存儲數據:
??實例對象就是通過類名alloc出來的對象,每次調用alloc生成新的實例對象,并將分配內存塊的首地址復制給實例對象的指針變量,因此每個實例對象的內存地址都不一樣。
ZBYMAPerson * instance = [ZBYMAPerson new];
ZBYMAPerson * instance2 = [ZBYMAPerson new];
ZBYMAPerson * instance3 = [ZBYMAPerson new];
// 輸出:實例對象:0x2823146f0-0x282314420-0x282314660
NSLog(@"實例對象:%p-%p-%p", instance, instance2, instance3);
??實例對象只保存成員變量。
??實例對象中存儲數據:
1.isa指針;
2.屬性值。
類對象的獲取和存儲數據:
??類對象是項目啟動時,runtime創建的類的單例對象,該類的實例對象的類對象有且只有一個;運行時,動態注冊一個類,就會生成于動態類對應的類對象。例如:KVO中觀察者動態子類的生成。
??獲取類對象可以用實例方法class或者runtime方法object_getClass獲得。
// 實例對象
ZBYMAPerson * instance = [ZBYMAPerson new];
ZBYMAPerson * instance2 = [ZBYMAPerson new];
ZBYMAPerson * instance3 = [ZBYMAPerson new];
// 類對象
Class class = object_getClass(instance);
// 輸出:類對象:0x104cbff30-0x104cbff30-0x104cbff30
NSLog(@"類對象:%p-%p-%p", class, instance2.class, [instance3 class]);
??可以看到不管用什么方法獲取的類對象的內存地址都相同,即在統一運行時有且只有一個類對象。
??類對象中存儲數據:
1.isa指針
2.superclass指針
3.類的屬性信息(@property),如成員變量的類型
4.類的對象方法信息
5.類的協議信息(protocol)
6.類的成員變量信息(ivar)
??成員變量的值是存儲在實例對象中的,因為只有當我們創建實例對象的時候才為成員變賦值。但是成員變量叫什么名字,是什么類型,只需要有一份就可以了;所以存儲在類對象中。
元類對象的創建和存儲數據:
??元類對象創建和類對象創建類似,也是一個單例對象。
??獲取元類對象可以用runtime方法object_getClass和objc_getMetaClass獲取。
// 實例對象
ZBYMAPerson * instance = [ZBYMAPerson new];
// 類對象
Class class = object_getClass(instance);
// 元類對象
Class metaClass = object_getClass(class);
NSString * className = NSStringFromClass(class);
const char * cClassName = [className UTF8String];
Class metaClass2 = objc_getMetaClass(cClassName);
// 元類對象:0x10034ff08-0x10034ff08
NSLog(@"元類對象:%p-%p", metaClass, metaClass2);
??通過上述代碼的輸出可以看出元類對象在同一運行時下,有且只有一個。
??元類對象存儲數據與類對象類似:
1.isa指針
2.superclass指針
3.類的類方法信息
3.類的屬性信息
isa和superclass指向:
總結:
??在同一運行時下,每一個類可以有多個實例對象,但是對應只有一個類對象和元類對象。
注意點:
?? class方法可以獲得class類對象,但是類對象調用class方法依舊是類對象,而不是元類對象。
// 實例對象
ZBYMAPerson * instance = [ZBYMAPerson new];
ZBYMAPerson * instance2 = [ZBYMAPerson new];
ZBYMAPerson * instance3 = [ZBYMAPerson new];
// 類對象
Class class = object_getClass(instance);
// 元類對象
Class metaClass = object_getClass(class);
NSString * className = NSStringFromClass(class);
const char * cClassName = [className UTF8String];
Class metaClass2 = objc_getMetaClass(cClassName);
NSLog(@"類對象:%p-%p-%p", [class class], [instance2.class class], [instance3 class]);
NSLog(@"元類對象:%p-%p", metaClass, metaClass2);