面试题涉及的知识点,都还在经典的isa&继承链图:面试
如下关于isKindOfClass
和isMemberOfClass
的类方法、实例方法的结果解析:markdown
// 类方法
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(@"\n 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(@"\n re5 :%hhd\n re6 :%hhd\n re7 :%hhd\n re8 :%hhd\n",re5,re6,re7,re8); 复制代码
经过查找源码,能够看到这两个方法的实现:优化
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = self->ISA(); 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; } 复制代码
可是咱们在断点调试过程当中,发现isKindOf的类方法和实例方法,并无被调用.实际上是被llvm作了底层逻辑优化,调用的方法会进入到objc_opt_isKindOfClass
.ui
// 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); } 复制代码
经过源码,咱们能够看到,isKindOf方法的内部逻辑是当前类指向的元类的继承链 与 要对比的类 进行比较
spa
BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
/* 1.NSObject的的元类是根元类==>tcls,tcls与NSObject对比为NO,tcls赋值根元类的父类 2.根元类的父类为根类==>tcls,tcls与NSObject对比为YES */ BOOL re3 = [(id)[LGPerson class] isKindOfClass:[LGPerson class]]; /* 1.LGPerson的元类为元类LGPerson==>tcls,tcls与LGPerson对比为NO,tcls赋值元类LGPerson的父类 2.元类LGPerson的父类为根元类==>tcls,tcls与LGperson对比为NO,tcls赋值根元类的父类 3.根元类的父类为根类NSObject==>tcls,tcls与LGPerson对比为NO,tcls赋值根类的父类nil */ 复制代码
+ (BOOL)isMemberOfClass:(Class)cls {
return self->ISA() == cls; } - (BOOL)isMemberOfClass:(Class)cls { return [self class] == cls; } 复制代码
isMemberOfClass类方法,是当前类对象的元类与其进行对比是否相等
;调试
isMemberOfClass实例方法,是当前实例对象的类与其进行对比是否相等
code
因此面试题的结果为:orm
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);
}
Class object_getClass(id obj)
{
if (obj) return obj->getIsa();
else return Nil;
}
复制代码