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;
}
複製代碼
相關文章
相關標籤/搜索