美文网首页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