美文网首页iOS进阶
07.3-Runtime中isMemberOfClass,isK

07.3-Runtime中isMemberOfClass,isK

作者: 光强_上海 | 来源:发表于2020-06-21 17:38 被阅读0次

我们新建一个工程,创建一个Person类,示例代码如下:

Person

@interface Person : NSObject

@end


@implementation Person

@end

main函数

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        Person *person = [[Person alloc] init];
        
        NSLog(@"%d", [person isMemberOfClass:[Person class]]); // 1
        NSLog(@"%d", [person isMemberOfClass:[NSObject class]]); // 0
        
        NSLog(@"%d", [person isKindOfClass:[Person class]]); // 1
        NSLog(@"%d", [person isKindOfClass:[NSObject class]]); // 1
    }
    return 0;
}

我们从main函数中的四个语句的打印,然后结合下面底层源码,我们可以看出结论:

  • -isMemberOfClass:判断左边的类对象是否等于右边的类对象
  • -isKindOfClass:判断左边的类对象是否等于右边的类对象,或者左边的类对象是右边的类对象的子类

上面的示例都是验证实例对象的用法,下面我们在验证下类对象的用法,示例代码如下:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        Person *person = [[Person alloc] init];
                
        NSLog(@"%d", [Person isMemberOfClass:[Person class]]); // 0
        NSLog(@"%d", [Person isKindOfClass:[Person class]]); // 0
        
        NSLog(@"%d", [Person isMemberOfClass:object_getClass([Person class])]); // 1
        
        NSLog(@"%d", [Person isKindOfClass:object_getClass([Person class])]); // 1
        
        NSLog(@"%d", [Person isKindOfClass:object_getClass([NSObject class])]); // 1
        
        // 这个比较特殊
        NSLog(@"%d", [[Person class] isKindOfClass:[NSObject class]]); // 1
    }
    return 0;
}

我们通过上面main函数中的打印结果和下面源码分析可以得出结论:

  • +isMemberOfClass:就是判断左边的元类对象是否等于右边的元类对象
  • +isKindOfClass:就是判断左边的元类对象是否等于右边的元类对象,或者左边的元类对象是右边的元类对象的子类

但是对于示例NSLog(@"%d", [[Person class] isKindOfClass:[NSObject class]]); // 1比较特殊,因为我们上面总结的+isKindOfClass右边都应该是元类对象进行比较,但是此示例中右边却是类对象,为什么打印还是1?

这是因为+isKindOfClass方法是遍历进行比较,当执行object_getClass([Person class])拿到的元类对象不等于右边时,就会通过superclass指针一层层往上找,直到找到基类的元类对象时左右两边还是不相等,此时则会从基类的元类对象找到基类的类对象,如下图红框所示,这时正好左边的类对象等于右边的类对象,所以打印结果为1

isa,superclass指针查找逻辑如图:

image

isMemberOfClassisKindOfClass底层源码查看路径:objc4源码 -> NSObject.mm -> isMemberOfClass -> isKindOfClass

isMemberOfClass实例方法

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

isMemberOfClass类方法

+ (BOOL)isMemberOfClass:(Class)cls {
    return object_getClass((id)self) == cls;
}

isKindOfClass实例方法

- (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}

isKindOfClass类方法

+ (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}

讲解示例Demo地址:https://github.com/guangqiang-liu/07.3-RunTime-isMemberOfClass-isKindOfClass

更多文章

相关文章

网友评论

    本文标题:07.3-Runtime中isMemberOfClass,isK

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