isKindOfClass和isMemberOfClass的区别

判断对象类型

-(BOOL) isKindOfClass: classObj判断是否是这个类或者这个类的子类的实例

-(BOOL) isMemberOfClass: classObj 判断是否是这个类的实例

接下来我们来看一道经典面试题:

    BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];       //
    BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];     //
    BOOL re3 = [(id)[LGPerson class] isKindOfClass:[LGPerson class]];       //
    BOOL re4 = [(id)[LGPerson class] isMemberOfClass:[LGPerson class]];     //
    NSLog(@" re1 :%hhd\n re2 :%hhd\n re3 :%hhd\n re4 :%hhd\n",re1,re2,re3,re4);

    BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]];       //
    BOOL re6 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]];     //
    BOOL re7 = [(id)[LGPerson alloc] isKindOfClass:[LGPerson class]];       //
    BOOL re8 = [(id)[LGPerson alloc] isMemberOfClass:[LGPerson class]];     //
    NSLog(@" re5 :%hhd\n re6 :%hhd\n re7 :%hhd\n re8 :%hhd\n",re5,re6,re7,re8);

输出结果
 re1 :1
 re2 :0
 re3 :0
 re4 :0
 re5 :1
 re6 :1
 re7 :1
 re8 :1

看到这个结果会不会很诧异,说实话我是很诧异ret3的结果
既然感到奇怪我们就来深入研究一下isKindOfClass和isMemberOfClass
首先通过调试我们定位到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);
}

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

这边有个宏__OBJC2__,当版本比较老,会通过objc_megSend调用isKindOfClass方法


注意到源码Class cls = obj->getIsa();这边拿的是obj的isa指向的类,我们知道对象的isa指向的是类,类的isa指向的是元类
[(id)[NSObject class] isKindOfClass:[NSObject class]];
这个拿的是NSObject根类的isa也就是根元类,和NSObject类对比,显然不是,后面通过循环,获取根元类的父类,根元类的父类是NSObject根类和NSObject类对比两个相同,所以返回true

[(id)[LGPerson class] isKindOfClass:[LGPerson class]];
同理,LGPerson的元类跟LGPerson类对比不同,而LGPerson元类的父类跟LGPerson也不一样,所以返回false

[(id)[NSObject alloc] isKindOfClass:[NSObject class]];
这边拿的是NSObject对象的isa,也就是NSObject类,所以是一样的

[(id)[LGPerson alloc] isKindOfClass:[LGPerson class]];
这边拿的是LGPerson对象的isa,也就是LGPerson类,所以是一样的

我们再来看看isMemberOfClass的源码

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

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

这个直接拿isa指针来跟cls对比,接下来我们来分析一下
BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];
[NSObject class]的isa是根元类,[NSObject class]根类,两个肯定不一样结果为false

[(id)[LGPerson class] isMemberOfClass:[LGPerson class]]
[LGPerson class]的isa是LGPerson元类,[LGPerson class]是LGPerson类,结果为false

[(id)[NSObject alloc] isMemberOfClass:[NSObject class]]
首先这边调用的是实例方法也就是上面的2这个代码 ,源码里面直接[self class] == cls,我们来分析一下[[NSObject alloc] class]=NSObject 类所以返回true

[(id)[LGPerson alloc] isMemberOfClass:[LGPerson class]]
同理,[[LGPerson alloc] class] = LGPerson类 所以也是返回true

你可能感兴趣的:(isKindOfClass和isMemberOfClass的区别)