isKindOfClass和isMemberOfClass - ShenYj/ShenYj.github.io GitHub Wiki

isKindOfClass和isMemberOfClass

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;
}

isMemberOfClass同样分为类方法和实例方法

/// 比较调用者的元类和目标类
+ (BOOL)isMemberOfClass:(Class)cls {
    return self->ISA() == cls;
}
/// 比较调用者的类对象和目标类
- (BOOL)isMemberOfClass:(Class)cls {
    return [self class] == cls;
}

在了解两者之间区别之前, 先要了解class实例方法和类方法的区别

/// 类方法返回的就是在自己
+ (Class)class {
    return self;
}
/// self为对象,结果是类对象
/// 非编译器优化方法
- (Class)class {
    return object_getClass(self);
}
Class object_getClass(id obj) {
    if (obj) return obj->getIsa();
    else return Nil;
}

经过编译器优化后,isKindOfClass实际调用的是objc_opt_isKindOfClass函数

// 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);
}
  • 类方法class返回自己

    • 类方法isKindOfClass比较的是调用者的元类\根元类 -> 父类 -> … 和目标类
    • 类方法isMemberOfClass比较的是调用者的元类\根元类和目标类
  • 实例方法class返回类对象

    • 实例方法isKindOfClass比较的是调用者的类对象 -> 父类 -> … 和目标类
    • 实例方法isMemberOfClass比较的是调用者的类对象 和目标类##

面试题

/// (传入值)NSObject类 -> 根元类 -> NSObject类  和  NSObject类  相等  1
BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];     
/// (传入值)NSObject类 -> 根元类  和 NSObject类 不相等 0
BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];   
/// (传入值)Son类 -> 元类 -> 根元类 ->  NSObject类  和  Son类   不相等 0
BOOL re3 = [(id)[Son class] isKindOfClass:[Son class]];    
/// (传入值)Son类 -> 元类  和  Son类   不相等 0
BOOL re4 = [(id)[Son class] isMemberOfClass:[Son class]];  

/// (传入值)NSObject对象 ->  NSObject类 和  NSObject类  相等  1
BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]];      
/// (传入值)NSObject对象 ->  NSObject类 和  NSObject类  相等  1
BOOL re6 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]];    
/// (传入值)Son对象 ->  Son类 和 Son类  相等  1
BOOL re7 = [(id)[Son alloc] isKindOfClass:[Son class]];     
/// (传入值)Son对象 ->  Son类 和 Son类  相等  1
BOOL re8 = [(id)[Son alloc] isMemberOfClass:[Son class]];  
⚠️ **GitHub.com Fallback** ⚠️