美文网首页
isKindOfClass or isMemberOfClass

isKindOfClass or isMemberOfClass

作者: 敏中 | 来源:发表于2020-12-01 15:32 被阅读0次

    概述

    先简单的说,两个都是NSObject用于比较 Class 的方法,不同之处在于:isKindOfClass可用于判断对象是否是一个类的成员,或者是该类子类的成员;isMemberOfClass可用于判断对象是否是当前类。或者可以这么理解:isKindOfClass 判断是否是自己或者父类, isMemberOfClass 判断是否是自己。
    isKindOfClass定义:Returns a Boolean value that indicates whether the receiver is an instance of given class or an instance of any class that inherits from that class.
    isMemberOfClass定义:Returns a Boolean value that indicates whether the receiver is an instance of a given class.

    解析:
    透过runtime源码分析到,其实类对象也可以使用这两个方法的:

    + (Class)class {
        return self;
    }
    
    - (Class)class {
        return object_getClass(self);
    }
    
    + (Class)superclass {
        return self->superclass;
    }
    
    - (Class)superclass {
        return [self class]->superclass;
    }
    
    + (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->superclass) {
            if (tcls == cls) return YES;
        }
        return NO;
    }
    
    - (BOOL)isKindOfClass:(Class)cls {
        for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
            if (tcls == cls) return YES;
        }
        return NO;
    }
    

    从runtime源码中我们可以看到类对象和实例对象分别有对应的+ (BOOL)isKindOfClass:(Class)cls和- (BOOL)isKindOfClass:(Class)cls方法。

    接下来举一些例子来详细认识:

    1.BOOL result1 = [[NSObject class] isKindOfClass:[NSObject class]];   // YES
    2.BOOL result2 = [[NSObject class] isMemberOfClass:[NSObject class]];  //NO
    3.BOOL result3 = [[Person class] isKindOfClass:[Person class]];   //NO
    4.BOOL result4 = [[Person class] isMemberOfClass:[Person class]];  //NO
    5.BOOL result5 = [[Person class] isKindOfClass:[NSObject class]];  // YES
    

    + (BOOL)isKindOfClass:(Class)cls分析:

    当调用对象为类对象的时候,我们可以发现其底层是一个循环遍历判断。
    BOOL result1 = [[NSObject class] isKindOfClass:[NSObject class]]
    当A对象为NSObject对象时,其isa指针指向的是NSObject元类(Meta),所以第一次循环元类和类对象肯定是不相等的。接下来第二次循环是元类对象的superclass指向的是NSObject本身,所以第二次循环是返回True的。

    ! image.png

    + (BOOL)isMemberOfClass:(Class)cls分析

    类方法中只是简单的做了一个isa指针和class之间的比较。所以,无论是NSObject的isa还是继承自NSObject的子类的isa都是指向A对象的元类,元类是类本身肯定是不一样的。

    针对上头的例子,都是类对象,具体来看:
    //问题1: 已经说明,有两次循环,第二次会相等
    BOOL result1 = [[NSObject class] isKindOfClass:[NSObject class]];

    //问题2:类方法是直接拿A对象的isa比较,元类和类不同,所以不相等
    BOOL result2 = [[NSObject class] isMemberOfClass:[NSObject class]];

    //问题3:逐次循环分析
    //第一次:Person->isa = Person Meta != Person
    //第二次:Person Meta -> superclass = NSObject Meta != Person
    //第三次:我们看到左边A对象的superclass会一直沿着关系图往上走,一直到nil都不会相等
    BOOL result3 = [[Person class] isKindOfClass:[Person class]];

    //和问题2相同也不会相等,类方法是直接拿A对象的isa比较,元类和类不同,所以不相等
    BOOL result4 = [[Person class] isMemberOfClass:[Person class]];

    //问题5:逐次循环分析
    //第一次:Person->isa = Person Meta != NSObject
    //第二次:Person Meta -> superclass = NSObject Meta != NSObject
    //第二次:NSObject Meta -> superclass = NSObject == Person
    5.BOOL result5 = [[Person class] isKindOfClass:[NSObject class]]; // YES

    第二波举例:

    NSArray *arr1 = [NSArray array];
    NSArray *arr2 = [NSArray array];
    NSObject *ob = [[NSObject alloc]  init];
     
    1.BOOL result1 =  [[NSArray array] isKindOfClass:[NSObject class]]; // YES
    2.BOOL result2 =   [[NSArray array] isMemberOfClass:[NSArray class]]; // NO
    3.BOOL result3 =  [arr1 isKindOfClass:[ob class]]; // YES
    4.BOOL result4 =  [arr1 isMemberOfClass:[ob class]]; // NO
    5.BOOL result5 =  [arr1 isKindOfClass:[arr2 class]]; // YES
    6.BOOL result6 =  [arr1 isMemberOfClass:[arr2 class]]; // YES
    

    针对上头的例子,都是类实例,具体来看:
    //问题1:逐次循环分析
    //第一次:[NSArray array] != [NSObject class]
    //第二次:[NSArray array] -> superclass = [NSObject class] == [NSObject class]
    1.BOOL result1 = [[NSArray array] isKindOfClass: [NSObject class]]; // YES

    //问题2:[NSArray array] == [NSArray class]
    //2.BOOL result2 = [[NSArray array] isMemberOfClass:[NSArray class]]; // NO

    //问题3:逐次循环分析
    //第一次:[NSArray array] != [NSObject class]
    //第二次:[NSArray array] -> superclass = [NSObject class] == [NSObject class]
    //3.BOOL result3 = [arr1 isKindOfClass:[ob class]]; // YES

    //问题4:[NSArray array] != [NSObject class]
    4.BOOL result4 = [arr1 isMemberOfClass:[ob class]]; // NO

    //问题5:逐次循环分析
    //第一次:[NSArray array] == [NSArray array]
    5.BOOL result5 = [arr1 isKindOfClass:[arr2 class]]; // YES

    //问题6:[NSArray array] == [NSArray array]
    6.BOOL result6 = [arr1 isMemberOfClass:[arr2 class]]; // YES

    相关文章

      网友评论

          本文标题:isKindOfClass or isMemberOfClass

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