objc_getClass和object_getClass
昨天打开好久没开的公众号后台,看到一个小伙伴 @阳光下的小泡沫星人002 给我留言,指正我之前写的关于Runtime的文章 中一个错误之处,并为此写了一篇文章 在此感谢。
这个错误是关于获取 NSObject
的元类的 isa
指针的问题。在我的文章中,错误的用 objc_getClass((__bridge void *)[NSObject class])
这种方式来获取对象的指针。代码如下:
void TestMetaClass(id self, SEL _cmd) {
NSLog(@"This objcet is %p", self);
NSLog(@"Class is %@, super class is %@", [self class], [self superclass]);
Class currentClass = [self class];
for (int i = 0; i < 4; i++) {
NSLog(@"Following the isa pointer %d times gives %p", i, currentClass);
currentClass = objc_getClass((__bridge void *)currentClass);
}
NSLog(@"NSObject's class is %p", [NSObject class]);
NSLog(@"NSObject's meta class is %p", objc_getClass((__bridge void *)[NSObject class])); // 0x0
}
实际上 objc_getClass
的参数是类名的字符串,获取指定类的类对象。上述代码中 (__bridge void *)[NSObject class])
的结果并不是类名的字符串,而是一个对象的指针,所以 objc_getClass
函数返回值的相当于是一个 nil
,打印指针的值就是 0x0
。所以正确使用 objc_getClass
的方式应该是objc_getClass("NSObject")
,其效果与 [NSObject class]
是一样的。
要想获取 NSObject
类对象的元类,可以使用 object_getClass
函数。这个函数参数是 id
类型,即一个对象,返回对象的 Class
信息,即对象的 isa
指针;如果传入的是一个类对象,获取的就是元类信息。
所以正确的代码如下,for
循环中的输出结果也印证了 NSObject
元类的isa指向的是其本身。
void TestMetaClass(id self, SEL _cmd) {
NSLog(@"This objcet is %p", self);
NSLog(@"Class is %@, super class is %@", [self class], [self superclass]);
Class currentClass = [self class];
for (int i = 0; i < 4; i++) {
NSLog(@"Following the isa pointer %d times gives %p", i, currentClass);
currentClass = object_getClass(currentClass);
}
// Following the isa pointer 0 times gives 0x10048e1f0
// Following the isa pointer 1 times gives 0x10048e220
// Following the isa pointer 2 times gives 0x7fff8c8e50f0
// Following the isa pointer 3 times gives 0x7fff8c8e50f0
NSLog(@"NSObject's class is %p", [NSObject class]);
NSLog(@"NSObject's meta class is %p", object_getClass([NSObject class]));
// NSObject's class is 0x7fff8c8e5140
// NSObject's meta class is 0x7fff8c8e50f0
}
由于博客已停更,错误之处可以在微博上私信。还请阅读的时候不要盲从。