一、面试题
- 面试题:
Person继承自NSObject,main函数中代码如下

- 此时打印是什么? 为什么是这种打印?
二、isKindOfClass:和isMemberOfClass:的底层源码
- 关于
isKindOfClass:和isMemberOfClass:两个方法, 底层代码是开源的

1、- (BOOL)isMemberOfClass:(Class)cls
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
- 可以看到方法的实现中, 是将
self的类方法, 与传入的Class进行对比, 如果相同返回YES, 否则返回NO

2、- (BOOL)isKindOfClass:(Class)cls
- (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
- 可以看到方法的实现中, 是先将
[self class]与传入cls对比,- 如果相同返回YES
- 如果不同就会取出
[[self class] supperclass]与cls对比
- 只要这个过程中有相同的情况就会返回
YES, 如果最后也没有匹配成功就会返回NO

3、+ (BOOL)isMemberOfClass:(Class)cls
+ (BOOL)isMemberOfClass:(Class)cls {
return object_getClass((id)self) == cls;
}
- 可以看到方法的实现中, 获取了
self的元类对象与传入的cls进行对比, 如果相同返回YES, 否则返回NO

4、+ (BOOL)isKindOfClass:(Class)cls
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
- 可以看到方法的实现中, 使用
self的元类对象与传入的cls进行对比- 如果相等返回
YES - 如果不相等, 就回取出
object_getClass(self)->superclass与cls对比, 依次类推
- 如果相等返回
- 只要这个过程中有相同的情况就会返回
YES, 如果最后也没有匹配成功就会返回NO

- 注意: 在上面的代码中, 有两句的结果是
1
// [NSObject class] == [NSObject class]
NSLog(@"%d", [[Person class] isKindOfClass:[NSObject class]]);
// [NSObject class] == [NSObject class]
NSLog(@"%d", [[NSObject class] isKindOfClass:[NSObject class]]);
- 在这两句中, 可以看到传入的
cls参数都是[NSObject class]
那么为什么, 这两句代码的结果相等呢?
- 在使用
superclass查找父类的过程中, 如果是通过元类对象查找, 根类NSObject元类对象的superclass是[NSObject class]

- 所以对于任何的元类对象, 只要一直查找
元类的superclass, 最终都会找到[NSOject class], 所以上面两句代码的结果是相等的
总结:
只要是isKindOfClass:方法的cls参数是[NSObject class], 那么调用者只要是NSObject或者NSObject的子类, 那么结果都是YES
三、解答面试题
// 元类对象最后会通过`superclass`找到[NSObject class], 所以结果相等, 结果是1
NSLog(@"%d", [NSObject isKindOfClass:[NSObject class]]);
// objc_getClass([NSObject class]) != [NSObject class] 结果是0
NSLog(@"%d", [NSObject isMemberOfClass:[NSObject class]]);
// objc_getClass([Person class]) != [Person class] 结果是0
NSLog(@"%d", [Person isKindOfClass:[Person class]]);
// objc_getClass([Person class]) != [Person class] 结果是0
NSLog(@"%d", [Person isMemberOfClass:[Person class]]);
