小碼哥iOS學習筆記第十五天: isKindOfClass:和isMemberOfClass:

1、面試題

  • 面試題: Person繼承自NSObject, main函數中代碼以下

  • 此時打印是什麼? 爲何是這種打印?

2、isKindOfClass:和isMemberOfClass:的底層源碼

  • 關於isKindOfClass:isMemberOfClass:兩個方法, 底層代碼是開源的

一、- (BOOL)isMemberOfClass:(Class)cls

- (BOOL)isMemberOfClass:(Class)cls {
    return [self class] == cls;
}
複製代碼
  • 能夠看到方法的實現中, 是將self的類方法, 與傳入的Class進行對比, 若是相同返回YES, 不然返回NO

二、- (BOOL)isKindOfClass:(Class)cls

- (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}
複製代碼
  • 能夠看到方法的實現中, 是先將[self class]與傳入cls對比,
    • 若是相同返回YES
    • 若是不一樣就會取出[[self class] supperclass]cls對比
  • 只要這個過程當中有相同的狀況就會返回YES, 若是最後也沒有匹配成功就會返回NO

三、+ (BOOL)isMemberOfClass:(Class)cls

+ (BOOL)isMemberOfClass:(Class)cls {
    return object_getClass((id)self) == cls;
}
複製代碼
  • 能夠看到方法的實現中, 獲取了self元類對象與傳入的cls進行對比, 若是相同返回YES, 不然返回NO

四、+ (BOOL)isKindOfClass:(Class)cls

+ (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}
複製代碼
  • 能夠看到方法的實現中, 使用self元類對象與傳入的cls進行對比
    • 若是相等返回YES
    • 若是不相等, 就回取出object_getClass(self)->superclasscls對比, 依次類推
  • 只要這個過程當中有相同的狀況就會返回YES, 若是最後也沒有匹配成功就會返回NO

  • 注意: 在上面的代碼中, 有兩句的結果是1
// [NSObject class] == [NSObject class]
NSLog(@"%d", [[Person class] isKindOfClass:[NSObject class]]);

// [NSObject class] == [NSObject class]
NSLog(@"%d", [[NSObject class] isKindOfClass:[NSObject class]]);
複製代碼
  • 在這兩句中, 能夠看到傳入的cls參數都是[NSObject class]

那麼爲何, 這兩句代碼的結果相等呢?面試

  • 在使用superclass查找父類的過程當中, 若是是經過元類對象查找, 根類NSObject元類對象superclass[NSObject class]

  • 因此對於任何的元類對象, 只要一直查找元類superclass, 最終都會找到[NSOject class], 因此上面兩句代碼的結果是相等的

總結:
只要是isKindOfClass:方法的cls參數是[NSObject class], 那麼調用者只要是NSObject或者NSObject的子類, 那麼結果都是YESbash

3、解答面試題

// 元類對象最後會經過`superclass`找到[NSObject class], 因此結果相等, 結果是1
NSLog(@"%d", [NSObject isKindOfClass:[NSObject class]]);

// objc_getClass([NSObject class]) != [NSObject class] 結果是0
NSLog(@"%d", [NSObject isMemberOfClass:[NSObject class]]);

// objc_getClass([Person class]) != [Person class] 結果是0
NSLog(@"%d", [Person isKindOfClass:[Person class]]);

// objc_getClass([Person class]) != [Person class] 結果是0
NSLog(@"%d", [Person isMemberOfClass:[Person class]]);
複製代碼

相關文章
相關標籤/搜索