简单使用
Person继承自NSObject
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSObject *obj = [[NSObject alloc] init];
Person *person = [[Person alloc] init];
BOOL res1 = [obj isKindOfClass:[NSObject class]]; // YES
BOOL res2 = [obj isMemberOfClass:[NSObject class]]; // YES
BOOL res3 = [person isKindOfClass:[Person class]]; // YES
BOOL res4 = [person isMemberOfClass:[Person class]]; // YES
NSLog(@"%d %d %d %d", res1, res2, res3, res4);
BOOL res5 = [[NSObject class] isKindOfClass:[NSObject class]]; // YES
BOOL res6 = [[NSObject class] isMemberOfClass:[NSObject class]]; // NO
BOOL res7 = [[Person class] isKindOfClass:[Person class]]; // NO
BOOL res8 = [[Person class] isMemberOfClass:[Person class]]; // NO
NSLog(@"%d %d %d %d", res5, res6, res7, res8);
}
return 0;
}
打印结果:
2020-08-28 17:26:00.062645+0800 LearningRuntime[13636:221035] 1 1 1 1
2020-08-28 17:26:00.064095+0800 LearningRuntime[13636:221035] 1 0 0 0
如上,若打印结果和你预期的一致,那恭喜你已经掌握了两者的本质,不需要再继续往下看了。
分析
想要理解打印的结果,最直接的方法就是看下isKindOfClass和isMemberOfClass的底层实现。在runtime源码的NSObject.mm文件中可以找到对应方法的实现。如下:
// 类方法
+ (BOOL)isMemberOfClass:(Class)cls {
return object_getClass((id)self) == cls;
}
// 实例方法
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
// 类方法
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
// 实例方法
- (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
由源码可知,isKindOfClass 和 isMemberOfClass 实例方法是拿类对象进行比较,类方法是拿元类对象进行比较。 所以上面的打印结果不难得出。
注意点:NSObject元类对象的superclass指针指向NSObject类对象。这就是 res5 结果为YES的原因。
图:
