isKindOfClass 和 isMemberOfClass 的区别
1、 BOOL reg1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
2、 BOOL reg2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];
3、 BOOL reg3 = [(id)[ELPerson class] isKindOfClass:[ELPerson class]];
4、 BOOL reg4 = [(id)[ELPerson class] isMemberOfClass:[ELPerson class]];
NSLog(@" reg1 :%hhd reg2 :%hhd reg3 :%hhd reg4 :%hhd",reg1,reg2,reg3,reg4);
5、 BOOL reg5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]];
6、 BOOL reg6 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]];
7、 BOOL reg7 = [(id)[ELPerson alloc] isKindOfClass:[ELPerson class]];
8、 BOOL reg8 = [(id)[ELPerson alloc] isMemberOfClass:[ELPerson class]];
NSLog(@" reg5 :%hhd reg6 :%hhd reg7 :%hhd reg8 :%hhd",reg5,reg6,reg7,reg8);
我们先看下打印的结果:
2021-06-21 17:10:52.925229+0800 002-isa分析[4583:220557] reg1 :1 reg2 :0 reg3 :0 reg4 :0
2021-06-21 17:10:52.925333+0800 002-isa分析[4583:220557] reg5 :1 reg6 :1 reg7 :1 reg8 :1
-(BOOL)isKindOfClass:(Class)aClass和+ (BOOL)isKindOfClass:(Class)cls
我们先看第一个和第三个。直接上源码分析:(我们发现类方法和对象方法的源码现在都是一样的,一起分析)
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);
}
通过查看代码我们发现- (BOOL)isKindOfClass:(Class)aClass;
的核心实现就是递归查找找类的元类的父类
和类
相比较的过程。
我们发现只有NSObject
的元类
的父类
是他自己
,其他的找到底都是NSObject,不能和类本身相等。
我们再看第五个和第七个
当实例对象
调用此方法时,就变成实例对象找类,然后递归找类的元类
和类
比较是否相等;
我们发现实例对象的isa
就是类
,所以:必然是相等的。
直接上isa的走位图,我们看的可能更清晰一些。
+ (BOOL)isMemberOfClass:(Class)cls和- (BOOL)isMemberOfClass:(Class)cls
我们直接上源码分析:
+ (BOOL)isMemberOfClass:(Class)cls {
return self->ISA() == cls;
}
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
我们发现类方法
是类对象
找isa
,也就是找类的元类
和类
比较;
看第二和第四个,很明显类的isa是元类,和类本身不相等;
对象方法
是获取对象
的类
和类
比较。
看第六个和第八个,获取对象的类和类本身是一样的,所以相等。