isKindOfClass和isMemberOfClass

278 阅读2分钟

isKindOfClass 和 isMemberOfClass有什么区别,底层是如何实现,结合源码分析具体是如何实现的。

isKindOfClass

isKindOfClass实现

直接通过源码查找isKindOfClass,可以找到一个类方法,一个类方法和一个实例方法,这里补充一点,在maocs10.15和ios13以及之后的版本中,将不会直接调用isKindOfClass方法,通过汇编可以看到调用的是objc_opt_isKindOfClass。

image.png

image.png

isKindOfClass源码分析

接下来将isKindOfClass 和 objc_opt_isKindOfClass拿出来分析。

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

// 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->getSuperclass()) {
            if (tcls == otherClass) return YES;
        }
        return NO;
    }
#endif
    return ((BOOL(*)(id, SEL, Class))objc_msgSend)(obj, @selector(isKindOfClass:), otherClass);
}

isKindOfClass 的类方法和实例方法都是oc函数,objc_opt_isKindOfClass很明显已经是c函数了。

  • isKindOfClass 流程。 类的元类 vs cls(需要比较的类),不同继续比较 。元类的父类 vs cls,不同继续比较直到找到根元类。根元类 vs cls,不同继续比较。根类(NSObject) vs cls,如果还不相同则根类(NSObject)的父类为nil,跳出循环返回NO
  • isKindOfClass 流程。获取当前对象所属类,类 vs cls,不同继续比较 。类的父类 vs cls,不同继续比较直到找到根类(NSObject)。 根类(NSObject) vs cls,如果还不相同则根类(NSObject)的父类为nil,跳出循环返回NO

isKindOfClass案例分析1

#import <Foundation/Foundation.h>


@interface LQPeople : NSObject
@end
@implementation LQPeople
@end


int main(int argc, const char * argv[]) {
    @autoreleasepool {
        BOOL b1 = [NSObject isKindOfClass:NSObject.class];
        BOOL b2 = [LQPeople isKindOfClass:LQPeople.class];
        
        
        NSLog(@"%d %d",b1,b2);
    }
    return 0;
}

分析 第一次循环明显不相等

image.png 进入第二次循环时相等了

image.png

isMemberOfClass

isMemberOfClass实现

直接通过源码查找isKindOfClass,可以找到一个类方法,一个类方法和一个实例方法。也不确定在未来时候会对这个进行优化,暂时没发现。

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

- (BOOL)isMemberOfClass:(Class)cls {
    return [self class] == cls;
}
  • isMemberOfClass 流程。 类的元类 vs cls(需要比较的类),相同就返回YES,否则返回NO
  • isMemberOfClass 流程。 类 vs cls(需要比较的类),相同就返回YES,否则返回NO

相比于isKindOfClass,isMemberOfClass就相对而言比较简单了。