Class
class本質(zhì)是一個結(jié)構(gòu)體的指針蜀撑,結(jié)構(gòu)體是objc_class
理张,這個結(jié)構(gòu)體中包含了:
- isa (實例->類->meta 類->root meta 類)root meta類指向本身
- 父類型的指針
- 類的名字
- 方法列表(可以是實例方法列表慷垮,也可以是類方法列表)
- 實現(xiàn)的協(xié)議列表
- 版本
- 保留的信息
id
id 本質(zhì)也是一個結(jié)構(gòu)體的指針,結(jié)構(gòu)體是objc_object
這個結(jié)構(gòu)體中包含:
struct objc_object { Class isa OBJC_ISA_AVAILABILITY; }
兩個獲取class的方法:
+(Class)class
這是一個類方法句灌,源碼是:
+ (Class)class { return self; }
類方法的class
是指向的自己本身夷陋,也許你在別人的代碼中看見這樣的一方法:
+(void)log {
[self.class logName];
// [self logName]; 他們是一個意思
}
這樣當(dāng)我們需要從一個類的實例對象來獲取isa鏈,那么我們不應(yīng)該通過這個類方法來獲取胰锌。
NSObject *objc = [NSObject new];
[objc class]; // class
[[objc class] class]; // meta class
[[[objc class] class] class]; // root meta class
你的本意是上面的意思骗绕,但是這個錯誤的其實這段代碼的含義是這樣的:
NSObject *objc = [NSObject new];
[objc class]; // class
[[objc class] class]; // class
[[[objc class] class] class]; // class
因為類方法
+(Class)class
返回的是self
-(Class)class
實例方法,源碼是:
- (Class)class { return object_getClass(self); }
我們從這個實例方法中我們可以看出來其實調(diào)用的是object_getClass(id)
那么這個方法的源碼是什么呢资昧?請看下一個章節(jié)
object_getClass
源碼:
Class object_getClass(id obj)
{
if (obj) return obj->getIsa();
else return Nil;
}
至于obj_getIsa()
這個方法是其實是獲取就是獲取Class結(jié)構(gòu)體中isa所指向的class指針酬土。你可以通過看源碼來了解obj_getIsa()
的具體實現(xiàn),源碼
我們可以通過
Class object_getClass(id obj)
來獲取isa鏈條
NSObject *objc = [NSObject new];
object_getClass(objc); // class
object_getClass(object_getClass(objc)); // meta class
object_getClass(object_getClass(object_getClass(objc))); //root meta class
我的問題
其實前面的知識榛搔,只是我通過看別的博客和簡書得知诺凡,這里也就是做個記錄,現(xiàn)在我要記錄一下我疑惑的地方践惑,并且通過做了驗證的:
{
Class personClass = [Person class];
NSLog(@"Class------%p", personClass);
[self logPropertyAndIvarWithClass:personClass];
Person *person = [Person new];
Class class = person.class;
NSLog(@"Object------%p", class);
[self logPropertyAndIvarWithClass:class];
// 通過實例方法的-(Class)class 和類方法+(Class)class他們指向都是同一個指針,我們知道類在程序中也是一個對象嘶卧,他們是一個單利尔觉。
}
- (void)logPropertyAndIvarWithClass:(Class)class {
unsigned int ivarCount = 0;
Ivar *ivars = class_copyIvarList(class, &ivarCount);
for (int i = 0 ; i < ivarCount; i++) {
Ivar ivar = ivars[i];
NSLog(@"ivar -- %@", [NSString stringWithUTF8String:ivar_getName(ivar)]);
}
unsigned int propertyCount = 0;
objc_property_t *properties = class_copyPropertyList(class, &propertyCount);
for (int i = 0 ; i < propertyCount; i++) {
objc_property_t property = properties[i];
NSLog(@"property -- %@", [NSString stringWithUTF8String:property_getName(property)]);
}
}
// 通過上面的兩個方法中,我知道ivar 要比property的數(shù)量多芥吟。
注意:根據(jù)runtime獲取出來的property侦铜,只能是自己本類的property专甩,而不能打印出 繼承父類 的property