isKindOfClass 和 isMemberOfClass的区别

146 阅读1分钟

isMemberOfClass:isKindOfClass: 两个方法的相关知识点。

以下打印结果是什么? (严谨点就添加个说明吧:Person 类继承于 NSObject 类)

BOOL res1 = [[NSObject class] isKindOfClass:[NSObject class]];
BOOL res2 = [[NSObject class] isMemberOfClass:[NSObject class]];
BOOL res3 = [[Person class] isKindOfClass:[Person class]];
BOOL res4 = [[Person class] isMemberOfClass:[Person class]];
NSLog(@"%d, %d, %d, %d", res1, res2, res3, res4);

打印结果:1, 0, 0, 0

+ (BOOL)isMemberOfClass:(Class)cls {
    return self->ISA() == cls;
}

- (BOOL)isMemberOfClass:(Class)cls {
    return [self class] == cls;
}

+ (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = self->ISA(); tcls; tcls = tcls->getSuperclass()) {
        if (tcls == cls) return YES;
    }
    return NO;
}

- (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = [self class]; tcls; tcls = tcls->getSuperclass()) {
        if (tcls == cls) return YES;
    }
    return NO;
}

由此我们可以得出结论:

  • isMemberOfClass: 方法是判断当前 instance/class 对象的 isa 指向是不是 class/meta-class 对象类型;
  • isKindOfClass: 方法是判断当前 instance/class 对象的 isa 指向是不是 class/meta-class 对象或者它的子类类型。

显然 isKindOfClass: 的范围更大。如果方法调用者是 instance 对象,传参就应该是 class 对象。如果方法调用着是 class 对象,传参就应该是 meta-class 对象。所以 res2-res4 都为 0。那为什么 res1 为 1 呢?

因为 NSObject 的 class 的对象的 isa 指向它的 meta-class 对象,而它的 meta-class 的 superclass 指向它的 class 对象,所以 [[NSObject class] isKindOfClass:[NSObject class]] 成立 。

相关文章

iOS摸鱼周报

isKindOfClass 和 isMemberOfClass的区别