开篇我们知道有 - (BOOL)isKindOfClass
、+(BOOL)isKindOfClass
、-(BOOL)isMemberOfClass
以及 + (BOOL)isMemberOfClass
四种判断方式。
首先我们编写如下代码:
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]];
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]];
+(BOOL)isKindOfClass 与 -(BOOL)isKindOfClass
前四个为类方法的判断,后四个为对象方法的判断。
我们使用断点调试,同时打开debug
-> Debug Workflow
->Always Show Disassembly
查看汇编流程。
通过断点我们看到与调用
+(BOOL)isKindOfClass
有关的是执行了objc_opt_isKindOfClass
,然后我们在可编译源码文件中查找此方法
// 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->superclass) {
if (tcls == otherClass) return YES;
}
return NO;
}
#endif
return ((BOOL(*)(id, SEL, Class))objc_msgSend)(obj, @selector(isKindOfClass:), otherClass);
}
此时我们知道当调用类方法或者实例方法的isKindOfClass
时,实际是调用了objc_opt_isKindOfClass
,在该方法中我们可以进行研究,根据isa
的走位图以及类的继承关系
我们可以进行判断,从而得到如下流程。
+(BOOL)isMemberOfClass 与 -(BOOL)isMemberOfClass
通过运行可编译文件以及断点调试可以得到如下代码实现
+ (BOOL)isMemberOfClass:(Class)cls {
return self->ISA() == cls;
}
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
因此可以得到,调用isMemberOfClass
的类方法是使用当前调用对象的isa与传入参数类进行对比,根据isa
走位,对象的isa
指向类
,类的isa
指向元类,元类的isa
指向根元类,根元类的isa
指向自身。调用isMemberOfClass
的实例方法是使用当前类和传入的类进行判断。
网友评论