iOS底层:isa面试题

面试题涉及的知识点,都还在经典的isa&继承链图:面试


面试题:

如下关于isKindOfClassisMemberOfClass的类方法、实例方法的结果解析: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); 复制代码

经过查找源码,能够看到这两个方法的实现:优化

1. isKindOfClass

+ (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


isKindOf类方法调用过程:

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 */ 复制代码

2.isMemberOfClass

+ (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;
}
复制代码
相关文章
相关标签/搜索