小码哥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]]);
复制代码

相关文章
相关标签/搜索