isKindOfClass和isMemberOfClass的区别

229 阅读1分钟
@interface MJPerson: NSObject
@end

NSLog(@"%d", [NSObject isKindOfClass:[NSObject class]]); // 1
NSLog(@"%d", [NSObject isMemberOfClass:[NSObject class]]); // 0
NSLog(@"%d", [MJPerson isKindOfClass:[MJPerson class]]); // 0
NSLog(@"%d", [MJPerson isMemberOfClass:[MJPerson class]]); // 0
2020-06-25 10:31:26.489715+0800 Interview01-class[87079:9497278] 1
2020-06-25 10:31:26.490295+0800 Interview01-class[87079:9497278] 0
2020-06-25 10:31:26.490728+0800 Interview01-class[87079:9497278] 0
2020-06-25 10:31:26.490792+0800 Interview01-class[87079:9497278] 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->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;
}

可以得出以下结论:

  • -isMemberOfClass: 是否等于传进来的类
  • -isKindOfClass: 是否等于传进来的类或者其父类
  • +isMemberOfClass: 元类对象是否等于传进来的类
  • +isMemberOfClass: 元类对象是否等于传进来的类或者父类

object_getClass是获取元类的方法

NSLog(@"%d", [MJPerson isMemberOfClass:object_getClass([MJPerson class])]);
NSLog(@"%d", [MJPerson isKindOfClass:object_getClass([NSObject class])]);
2020-06-25 10:48:45.867877+0800 Interview01-class[87151:9508180] 1
2020-06-25 10:48:45.867912+0800 Interview01-class[87151:9508180] 1

这句代码结果为1的原因

NSLog(@"%d", [NSObject isKindOfClass:[NSObject class]]); // 1

注意以下类和元类的关系中的红色箭头,可以看出元类的基类的superclass指针最终指向的是类的基类。所以这句循环最后的一步判断结果就是

if ([NSObject class] == [NSObject class])

所以结果为1