美文网首页iOS Runtime
isKindOfClass和isMemberOfClass的区别

isKindOfClass和isMemberOfClass的区别

作者: 木扬音 | 来源:发表于2020-09-20 22:57 被阅读0次

    想要深入立即isKindOfClassisMemberOfClass的区别,那就离不开下面这个图

    image.png

    isa 走位链(两条)

    • teacher的isa走位链:teacher(子类对象) --> CJLTeacher (子类)--> CJLTeacher(子元类) --> NSObject(根元类) --> NSObject(跟根元类,即自己)

    • person的isa走位图:person(父类对象) --> CJLPerson (父类)--> CJLPerson(父元类) --> NSObject(根元类) --> NSObject(跟根元类,即自己)

    superclass走位链(两条)

    • 类的继承关系链:CJLTeacher(子类) --> CJLPerson(父类) --> NSObject(根类)--> nil

    • 元类的继承关系链:CJLTeacher(子元类) --> CJLPerson(父元类) --> NSObject(根元类)--> NSObject(根类)--> nil

    示例分享

    //LGPerson 继承自 NSObject
    BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];        
    BOOL re2 = [(id)[LGPerson class] isKindOfClass:[LGPerson class]];    
    BOOL re3 = [(id)[NSObject class] isMemberOfClass:[NSObject 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)[LGPerson alloc] isKindOfClass:[LGPerson class]];          
    BOOL re7 = [(id)[NSObject alloc] isMemberOfClass:[NSObject 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);
    
    输出
    2020-09-20 21:15:13.975631+0800 KCObjc[2274:69804]  
     re1 :1
     re2 :0
     re3 :0
     re4 :0
    2020-09-20 21:15:13.976631+0800 KCObjc[2274:69804]  
     re5 :1
     re6 :1
     re7 :1
     re8 :1
    

    源码分析

    + (BOOL)isKindOfClass:(Class)cls

    + (BOOL)isKindOfClass:(Class)cls {
        for (Class tcls = self->ISA(); tcls; tcls = tcls->superclass) {
            // 获取类的元类 vs 传入类
            // 根元类 vs 传入类
            // 根类 vs 传入类
            if (tcls == cls) return YES;
        }
        return NO;
    }
    
    • 1、 BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
    • 传入的clsNSObject(根类)self 指向 NSObject,进入循环
    • tcls= NSObject meta(根元类),执行判断if (tcls == cls),不相等,进入下一个循环
    • tcls= NSObject(根类),执行判断if (tcls == cls),相等,return YES
    • 2、 BOOL re2 = [(id)[LGPerson class] isKindOfClass:[LGPerson class]];
    • 传入的clsLGPersonself 指向 LGPerson,进入循环
    • tcls= LGPerson meta(元类),执行判断if (tcls == cls),不相等,进入下一个循环
    • tcls= NSObject meta(根元类),执行判断if (tcls == cls),不相等,进入下一个循环
    • tcls= NSObject meta(根类),执行判断if (tcls == cls),不相等,进入下一个循环
    • tcls= nil,结束循环,

    + (BOOL)isMemberOfClass:(Class)cls

    + (BOOL)isMemberOfClass:(Class)cls {
        //获取类的元类,与 传入类对比
        return self->ISA() == cls;
    }
    
    • 3、 BOOL re3 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];
    • 传入的clsNSObject(根类)self 指向 NSObject,进入循环
    • tcls= NSObject meta(根元类),执行判断if (tcls == cls),不相等
    • 4、 BOOL re4 = [(id)[LGPerson class] isMemberOfClass:[LGPerson class]];
    • 传入的clsLGPersonself 指向 LGPerson,进入循环
    • tcls= NSObject meta(元类),执行判断if (tcls == cls),不相等

    - (BOOL)isKindOfClass:(Class)cls

    - (BOOL)isKindOfClass:(Class)cls {
        //获取对象的类 vs 传入的类 
        //父类 vs 传入的类
        //根类 vs 传入的类
        for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
            if (tcls == cls) return YES;
        }
        return NO;
    }
    
    • 1、 BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]];
    • 传入的clsNSObject(根类)self 指向 NSObject实例对象,进入循环,NSObject实例对象的isa即NSObject(根类)
    • tcls= NSObject(根类),执行判断if (tcls == cls),相等
    • 2、 BOOL re6 = [(id)[LGPerson alloc] isKindOfClass:[LGPerson class]];
    • 传入的clsLGPersonself 指向 LGPerson实例对象,进入循环,LGPerson实例对象的isa即LGPerson
    • tcls= LGPerson,执行判断if (tcls == cls),相等

    - (BOOL)isMemberOfClass:(Class)cls

    - (BOOL)isMemberOfClass:(Class)cls {
        //获取对象的类,与 传入类对比
        return [self class] == cls;
    }
    
    • 1、 BOOL re7 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]];
    • 传入的clsNSObject(根类)self 指向 NSObject实例对象,进入循环,NSObject实例对象的即NSObject(根类)
    • tcls= NSObject(根类),执行判断if (tcls == cls),相等
    • 2、 BOOL re8 = [(id)[LGPerson alloc] isMemberOfClass:[LGPerson class]];
    • 传入的clsLGPersonself 指向 LGPerson实例对象,进入循环,LGPerson实例对象的即LGPerson
    • tcls= LGPerson,执行判断if (tcls == cls),相等

    总结

    isKindOfClass

    • 类方法:元类的继承链对比
      • 元类(isa) --> 根元类(父类) --> 根类(父类) --> nil(父类)
    • 实例方法:对象的类 --> 父类 --> 根类 --> nil传入类的对比

    isMemberOfClass

    • 类方法: 类的元类传入类 对比
    • 实例方法:对象的父类传入类 对比

    相关文章

      网友评论

        本文标题:isKindOfClass和isMemberOfClass的区别

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