- 深入理解isKindOfClass、isMemberOfClas
- isKindOfClass: / isMemberOfClas
- isKindOfClass: & isMemberOfClas
- iOS isKindOfClass,isMemberOfClas
- iOS isKindOfClass、isMemberOfClas
- iOS isKindOfClass isMemberOfClas
- iOS中isKindOfClass,isMemberOfClas
- iOS isKindOfClass&isMemberOfClas
- iOS isKindOfClass与isMemberOfClas
- iOS中isKindOfClass和isMemberOfClas
首先先看一段代码
static void lgKindofDemo(void){
BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]]; //
BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]]; //
BOOL re3 = [(id)[LGPerson class] isKindOfClass:[LGPerson class]]; //
BOOL re4 = [(id)[LGPerson class] isMemberOfClass:[LGPerson class]]; //
NSLog(@" re1 :%hhd\n re2 :%hhd\n re3 :%hhd\n re4 :%hhd\n",re1,re2,re3,re4);
BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]]; //
BOOL re6 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]]; //
BOOL re7 = [(id)[LGPerson alloc] isKindOfClass:[LGPerson class]]; //
BOOL re8 = [(id)[LGPerson alloc] isMemberOfClass:[LGPerson class]]; //
NSLog(@" re5 :%hhd\n re6 :%hhd\n re7 :%hhd\n re8 :%hhd\n",re5,re6,re7,re8);
}
这段代码的打印结果是,class类方法比对的只要re1是1,alloc类方法比对的全部都是1;
re1 :1
re2 :0
re3 :0
re4 :0
re5 :1
re6 :1
re7 :1
re8 :1
源码奉上
+ (Class)class {
return self;
}
- (Class)class {
return object_getClass(self);
}
+ (BOOL)isMemberOfClass:(Class)cls {
return self->ISA() == cls;
}
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
+ (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;
}
1、isMemberOfClass vc isKindOfClass
isMemberOfClass、isKindOfClass底层实现,可以看的出来,isMemberOfClass只是比对当前的class,而isKindOfClass会通过getSuperClass层层往上找;
2、class vc alloc
因为[NSObject class]返回的是一个Class类,而[LGPerson alloc] 是返回一个对象,对象是通过self.class进行比较的,而类是通过self->isa进行比较;
alloc都是1就很明显了,因为继承链的关系,主要分析一下为什么class只有re1的结果是1;
这里主要就是因为类方法是通过isa进行对比,而类的isa指向元类,相当于是拿一个元类跟类做对比,比不了再拿元类的父类进行对比;
因为元类的父类 == 父类的元类,即Person元类的父类 == NSObject的元类,所以Person比较肯定都不行,因为根类的元类也是指向根类的元类,而根元类的父类是它本身,即NSObject,所以唯独[NSObject class]的isKind会成立,
- [NSObject class] iisknd => NSObject 元类 vs NSObject,显然是不成立的;
在往上是NSObject 元类的父类 == NSObject vs NSObject,成立; - [NSObject class] member => NSObject 元类 vs NSObject,显然是不成立的
- [LGPerson class] iskind => LGPerson 元类 vs LGPerson,显然不成立的;在往上就是LGPerson 元类的父类 == NSObject的元类 vs LGPerson,也不成立的;再往上就回到了跟第一个一样的判断了,就不再重复了
- [LGPerson class] member => LGPerson 元类 vs LGPerson,显然也不成立的
具体参考isa流程图
isa流程图.png
3、isKindOfClass底层调用
查看汇编执行流程
image.png
isKindOfClass底层调用
会发现它底层实际是调用了objc_opt_isKindOfClass,这跟我之前分析OC对象原理的时候,提到alloc的调用流程也是如此,通过LLVM重定向,先经过一层加工判断之后,再通过消息转发,执行isKindOfClass;
// Calls [obj isKindOfClass]
BOOL
objc_opt_isKindOfClass(id obj, Class otherClass)
{
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;
}
return ((BOOL(*)(id, SEL, Class))objc_msgSend)(obj, @selector(isKindOfClass:), otherClass);
}
alloc调用
网友评论