相关链接:objc4-750配置下载教程
日常开发中,我们想必会经常通过isKindOfClass和isMemberOfClass去处理一些逻辑判断,但是我们真的了解它们吗?
话不多说我们直接上场景:
@interface Person : NSObject
@end
@implementation Person
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];
BOOL re3 = [(id)[Person class] isKindOfClass:[Person class]];
BOOL re4 = [(id)[Person class] isMemberOfClass:[Person class]];
NSLog(@" re1 :%hhd re2 :%hhd re3 :%hhd re4 :%hhd ",re1,re2,re3,re4);
}
return 0;
}
输出结果:
2019-08-21 17:01:00.054439+0800 001-isKindOfClass&isMemberOfClass[25960:1615638] re1 :1 re2 :0 re3 :0 re4 :0
接下来我们通过objc源码来分析为什么会是输出这个样的一个结果~
+ (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中有一个循环,先判断当前类是否等于元类,不等就继续循环取元类的父类进行判断,不等再继续取父类,如此循环下去。
然而此时我们需要上isa走向图:
[NSObject class] 调用 isKindOfClass,第一次判断先判断NSObject 和 NSObject的元类是否相等,从图上我们也可以看出,NSObject的元类是根元类。接着第二次循环判断NSObject与根元类的父类是否相等。还是从那张图上面我们可以看到:根元类 的父类也就是NSObject本身。所以第二次循环相等,于是第一行res1输出应该为YES。
[Person class] 调用 isKindOfClass,第一次for循环,Person的元类与[Person class]不等,第二次for循环,Person元类的父类 指向的是 NSObject Meta Class(根元类), 和[Person class]不相等。第三次for循环,根元类指向的是NSObject,和 [Person Class] 不相等。第四次循环,NSObject Class 的父类 指向 nil, 和 Person Class不相等。第四次循环之后,退出循环,所以第三行的res3输出为NO。
isMemberOfClass的源码实现是拿到自己的isa指针和自己比较,是否相等。
第二行 isa 指向 NSObject 的 元类,所以和 NSObject不相等。第四行,isa指向Person的元类,和Perosn Class也不等,所以第二行res2和第四行res4都输出NO。