蘋果官方維護(hù)的objc源代碼
我們常說OC是一種面向?qū)ο蟮恼Z言,那么
什么是對象顽腾?
類:對同一類事物的高度抽象际乘。類定義了這一類的屬性以及行為準(zhǔn)則(方法)。
對象:類的一個實(shí)例衔肢,是一個具體的事物颠通。
1. runtime中的類和對象
typedef struct objc_class *Class;
typedef struct objc_object *id;
簡單從定義來看:Class是一個objc_class結(jié)構(gòu)類型的指針,id(任意對象)是一個objc_object結(jié)構(gòu)類型的指針
再來看下這兩個結(jié)構(gòu)體objc_class
和objc_object
/// objc_class
struct objc_class {
Class isa;
Class super_class;
const char *name;
long version;
long info;
long instance_size;
struct objc_ivar_list *ivars;
struct objc_method_list *methodLists;
struct objc_cache *cache;
struct objc_protocol_list *protocols;
} ;
/// objc_object
struct objc_object {
Class isa;
};
objc_class和objc_object都有一個isa指針膀懈,我們知道實(shí)例的isa指針指向?qū)嵗鶎俚念惗倜蹋磑bjc_object中的isa指針指向了objc_object所屬的類objc_class,那么
objc_class中的isa指針指向哪里呢启搂?
2. 元類 MetaClass
先看結(jié)論
每一個類本質(zhì)上都是一個對象硼控,類其實(shí)是元類(meteClass)的實(shí)例。類通過類的isa指針指向元類胳赌。所有的元類最終繼承一個根元類牢撼,根元類isa指針指向本身,形成一個封閉的內(nèi)循環(huán)疑苫。
看到這里我又疑惑了熏版,實(shí)例的isa指向它所屬的類,類的isa指向它的元類捍掺,類的元類是什么撼短,是它所繼承的父類嗎,那么類的isa(元類)和super_class(父類)是不是有關(guān)系呢挺勿?
還是要來段代碼測試一下:
Class class1 = [[NSString alloc] init].class;
Class class = [NSString class];
Class superClass = [NSString superclass];
NSLog(@"%@:%p",NSStringFromClass(class1), class1);
NSLog(@"%@:%p",NSStringFromClass(class), class);
NSLog(@"%@:%p",NSStringFromClass(superClass), superClass);
//輸出結(jié)果
2018-06-02 08:17:46.802684+0800 RuntimeDemo[1129:82727] __NSCFConstantString:0x108679fe0
2018-06-02 08:17:46.802851+0800 RuntimeDemo[1129:82727] NSString:0x107abad68
2018-06-02 08:17:46.802989+0800 RuntimeDemo[1129:82727] NSObject:0x1080feea8
測試發(fā)現(xiàn)曲横,NSString的元類([NSString class])并不是我以為的NSObject,而是NSString,那么實(shí)例的isa指針和類的isa指針指向到底哪里不一樣呢?還是code一下看看吧
先寫個方法輸出Class的詳細(xì)信息
- (void)getInfoFromClass:(Class)cls {
/// class_getName 獲取類name
NSLog(@"%s:%p",class_getName(cls), cls);
/// class_isMetaClass用于判斷Class對象是否為元類禾嫉,
BOOL isMeta = class_isMetaClass(cls);
NSLog(@"%@",isMeta?@"是元類":@"不是元類");
// 成員變量
unsigned int outCount = 0;
NSLog(@"成員變量 class_copyIvarList:");
Ivar *ivars = class_copyIvarList(cls, &outCount);
for (int i = 0; i < outCount; i++) {
Ivar ivar = ivars[i];
NSLog(@"%s",ivar_getName(ivar));
}
free(ivars);
// 屬性操作
NSLog(@"屬性 class_copyPropertyList:");
objc_property_t * properties = class_copyPropertyList(cls, &outCount);
for (int i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
NSLog(@"%s", property_getName(property));
}
free(properties);
// 方法操作
NSLog(@"方法 class_copyMethodList:");
Method *methods = class_copyMethodList(cls, &outCount);
for (int i = 0; i < outCount; i++) {
Method method = methods[i];
SEL sel = method_getName(method);
NSLog(@"%@",NSStringFromSelector(sel));
}
free(methods);
}
再自定義個Person類(這里為什么不用系統(tǒng)的類呢灾杰,因為系統(tǒng)的類方法太多了,輸出那么多影響觀察)
#pragma mark - 定義一個類Person
@interface Person : NSObject
+ (void)staticDescription;
- (void)instanceDescription;
@end
@implementation Person
+ (void)staticDescription { }
- (void)instanceDescription { }
@end
OK熙参,定義了一個類Person艳吠,Person包含一個類方法一個實(shí)例方法,打印一下看看
Person *person = [[Person alloc] init];
/// object_getClass用于獲取對象的isa指針指向的對象孽椰。
[self getInfoFromClass:object_getClass(person)];
[self getInfoFromClass:object_getClass(Person.class)];
/// 輸出結(jié)果
2018-06-02 09:32:32.473784+0800 RuntimeDemo[2398:280748] Person:0x109bf7010
2018-06-02 09:32:32.473922+0800 RuntimeDemo[2398:280748] 不是元類
2018-06-02 09:32:32.474260+0800 RuntimeDemo[2398:280748] 方法 class_copyMethodList:
2018-06-02 09:32:32.474382+0800 RuntimeDemo[2398:280748] instanceDescription
2018-06-02 09:32:32.474484+0800 RuntimeDemo[2398:280748] Person:0x109bf6fe8
2018-06-02 09:32:32.474635+0800 RuntimeDemo[2398:280748] 是元類
2018-06-02 09:32:32.474960+0800 RuntimeDemo[2398:280748] 方法 class_copyMethodList:
2018-06-02 09:32:32.475084+0800 RuntimeDemo[2398:280748] staticDescription
看到了吧讲竿,實(shí)例的isa指針指向它所屬的類,類的isa指針指向的是類對象的元弄屡。類對象存的是關(guān)于實(shí)例對象的信息(變量,實(shí)例方法等)鞋诗,而元類對象(metaclass object)中存儲的是關(guān)于類的信息(類的版本膀捷,名字,類方法等)削彬。
所以類也是對象全庸,是元類的對象
類對象和實(shí)例對象的區(qū)別:盡管類對象保留了一個類實(shí)例的原型,但它并不是實(shí)例本身融痛。它沒有自己的實(shí)例變量壶笼,也不能執(zhí)行那些類的實(shí)例的方法(只有實(shí)例對象才可以執(zhí)行實(shí)例方法)。然而雁刷,類的定義能包含那些特意為類對象準(zhǔn)備的方法–類方法( 而不是的實(shí)例方法)覆劈。類對象從父類那里繼承類方法,就像實(shí)例從父類那里繼承實(shí)例方法一樣沛励。
來看下說明圖:
參考鏈接:
http://www.reibang.com/p/41735c66dccb
http://justsee.iteye.com/blog/2163905
http://www.zhimengzhe.com/IOSkaifa/253119.html