isKindOfClass 和 isMemberOfClass有什么区别,底层是如何实现,结合源码分析具体是如何实现的。
isKindOfClass
isKindOfClass实现
直接通过源码查找isKindOfClass,可以找到一个类方法,一个类方法和一个实例方法,这里补充一点,在maocs10.15和ios13以及之后的版本中,将不会直接调用isKindOfClass方法,通过汇编可以看到调用的是objc_opt_isKindOfClass。
isKindOfClass源码分析
接下来将isKindOfClass 和 objc_opt_isKindOfClass拿出来分析。
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = self->ISA(); tcls; tcls = tcls->getSuperclass()) {
if (tcls == cls) return YES;
}
return NO;
}
- (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = [self class]; tcls; tcls = tcls->getSuperclass()) {
if (tcls == cls) return YES;
}
return NO;
}
// Calls [obj isKindOfClass]
BOOL objc_opt_isKindOfClass(id obj, Class otherClass)
{
#if __OBJC2__
if (slowpath(!obj)) return NO;
Class cls = obj->getIsa();
if (fastpath(!cls->hasCustomCore())) {
for (Class tcls = cls; tcls; tcls = tcls->getSuperclass()) {
if (tcls == otherClass) return YES;
}
return NO;
}
#endif
return ((BOOL(*)(id, SEL, Class))objc_msgSend)(obj, @selector(isKindOfClass:), otherClass);
}
isKindOfClass 的类方法和实例方法都是oc函数,objc_opt_isKindOfClass很明显已经是c函数了。
- isKindOfClass 流程。 类的元类 vs cls(需要比较的类),不同继续比较 。元类的父类 vs cls,不同继续比较直到找到根元类。根元类 vs cls,不同继续比较。根类(NSObject) vs cls,如果还不相同则根类(NSObject)的父类为nil,跳出循环返回NO
- isKindOfClass 流程。获取当前对象所属类,类 vs cls,不同继续比较 。类的父类 vs cls,不同继续比较直到找到根类(NSObject)。 根类(NSObject) vs cls,如果还不相同则根类(NSObject)的父类为nil,跳出循环返回NO
isKindOfClass案例分析1
#import <Foundation/Foundation.h>
@interface LQPeople : NSObject
@end
@implementation LQPeople
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
BOOL b1 = [NSObject isKindOfClass:NSObject.class];
BOOL b2 = [LQPeople isKindOfClass:LQPeople.class];
NSLog(@"%d %d",b1,b2);
}
return 0;
}
分析 第一次循环明显不相等
进入第二次循环时相等了
isMemberOfClass
isMemberOfClass实现
直接通过源码查找isKindOfClass,可以找到一个类方法,一个类方法和一个实例方法。也不确定在未来时候会对这个进行优化,暂时没发现。
+ (BOOL)isMemberOfClass:(Class)cls {
return self->ISA() == cls;
}
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
- isMemberOfClass 流程。 类的元类 vs cls(需要比较的类),相同就返回YES,否则返回NO
- isMemberOfClass 流程。 类 vs cls(需要比较的类),相同就返回YES,否则返回NO
相比于isKindOfClass,isMemberOfClass就相对而言比较简单了。