美文网首页
深入探究isKindOfClass、isMemberOfClas

深入探究isKindOfClass、isMemberOfClas

作者: 星星杨 | 来源:发表于2023-02-02 00:10 被阅读0次

首先先看一段代码

static void lgKindofDemo(void){
    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);
}

这段代码的打印结果是,class类方法比对的只要re1是1,alloc类方法比对的全部都是1;

 re1 :1
 re2 :0
 re3 :0
 re4 :0
 re5 :1
 re6 :1
 re7 :1
 re8 :1

源码奉上

+ (Class)class {
    return self;
}

- (Class)class {
    return object_getClass(self);
}

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

1、isMemberOfClass vc isKindOfClass

isMemberOfClass、isKindOfClass底层实现,可以看的出来,isMemberOfClass只是比对当前的class,而isKindOfClass会通过getSuperClass层层往上找;

2、class vc alloc

因为[NSObject class]返回的是一个Class类,而[LGPerson alloc] 是返回一个对象,对象是通过self.class进行比较的,而类是通过self->isa进行比较;
alloc都是1就很明显了,因为继承链的关系,主要分析一下为什么class只有re1的结果是1;
这里主要就是因为类方法是通过isa进行对比,而类的isa指向元类,相当于是拿一个元类跟类做对比,比不了再拿元类的父类进行对比;
因为元类的父类 == 父类的元类,即Person元类的父类 == NSObject的元类,所以Person比较肯定都不行,因为根类的元类也是指向根类的元类,而根元类的父类是它本身,即NSObject,所以唯独[NSObject class]的isKind会成立,

  • [NSObject class] iisknd => NSObject 元类 vs NSObject,显然是不成立的;
    在往上是NSObject 元类的父类 == NSObject vs NSObject,成立;
  • [NSObject class] member => NSObject 元类 vs NSObject,显然是不成立的
  • [LGPerson class] iskind => LGPerson 元类 vs LGPerson,显然不成立的;在往上就是LGPerson 元类的父类 == NSObject的元类 vs LGPerson,也不成立的;再往上就回到了跟第一个一样的判断了,就不再重复了
  • [LGPerson class] member => LGPerson 元类 vs LGPerson,显然也不成立的

具体参考isa流程图


isa流程图.png

3、isKindOfClass底层调用

查看汇编执行流程


image.png
isKindOfClass底层调用

会发现它底层实际是调用了objc_opt_isKindOfClass,这跟我之前分析OC对象原理的时候,提到alloc的调用流程也是如此,通过LLVM重定向,先经过一层加工判断之后,再通过消息转发,执行isKindOfClass;

// Calls [obj isKindOfClass]
BOOL
objc_opt_isKindOfClass(id obj, Class otherClass)
{
    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;
    }

    return ((BOOL(*)(id, SEL, Class))objc_msgSend)(obj, @selector(isKindOfClass:), otherClass);
}
alloc调用

相关文章

网友评论

      本文标题:深入探究isKindOfClass、isMemberOfClas

      本文链接:https://www.haomeiwen.com/subject/gekwhdtx.html