Battle系列之isKindOfClass VS isMemberOfClass

347 阅读4分钟

本文主要目的是分析二者之间的关系和区别:

 - (BOOL)isKindOfClass:(Class)aClass;
 - (BOOL)isMemberOfClass:(Class)aClass;

 + (BOOL)isKindOfClass:(Class)aClass;
 + (BOOL)isMemberOfClass:(Class)aClass;

划重点:此文章只讨论对象之间的比较

首先我们先来搞一下runtime的结构图

这个图就不赘述了,不是本文的重点。但是我们还是要先明确的概念:

类和元类打印对象结果名字虽然相同但是地址完全不同,这是2个内存地址

上源码:

+ (BOOL)isMemberOfClass:(Class)cls {
    return self->ISA() == cls;
}
// self->ISA() 表示当前类型 返回的是一个Class
// cls 传入的类型

- (BOOL)isMemberOfClass:(Class)cls {
    return [self class] == cls;
}
/**
- (Class)class {
    return object_getClass(self);
} 
[self class]返回的就是Class
**/

+ (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = self->ISA(); tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}
/**
到了kind方法当中则是去循环判断
获取当前的ISA所指向的类,如果和当前类不想等,则去找他的父类
按照这个逻辑不停的向上循环,如果找到当前的类对象就返回成功,否则返回false
**/

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

/**
到了kind方法当中则是去循环判断
获取当前的类对象,如果和当前类不想等,则去找他的父类
按照这个逻辑不停的向上循环,如果找到当前的类对象就返回成功,否则返回false
**/

举个栗子, 我们就来分析接下来的源码

  - (void)viewDidLoad {
    [super viewDidLoad];
    Person *person = [[Person alloc] init];
    Man *man = [[Man alloc] init];  //Man是Person的子类
    NSObject *obj = [[NSObject alloc] init];
    
    //对象方法
    if ([person isMemberOfClass:[Person class]]) {
        NSLog(@"person isMemberOfClass: Person");
    } else {
        NSLog(@"person is't member of Person");
    }
    if ([man isMemberOfClass:[Person class]]) {
        NSLog(@"man isMemberOfClass: Person");
    } else {
        NSLog(@"man is't member of Person");
    }
    if ([obj isMemberOfClass:[NSObject class]]) {
        NSLog(@"obj isMemberOfClass: NSObject");
    } else {
        NSLog(@"obj is't member of NSObject");
    }
    //类方法
    if ([Person isMemberOfClass:[Person class]]) {
        NSLog(@"Person isMemberOfClass: Person");
    } else {
        NSLog(@"Person is't member of Person");
    }
    if ([Man isMemberOfClass:[Person class]]) {
        NSLog(@"Man isMemberOfClass: Person");
    } else {
        NSLog(@"Man is't member of Person");
    }
    if ([NSObject isMemberOfClass:[NSObject class]]) {
        NSLog(@"NSObject isMemberOfClass: NSObject");
    } else {
        NSLog(@"NSObject is't member of NSObject");
    }
    
    
    //对象方法
    if ([person isKindOfClass:[Person class]]) {
        NSLog(@"person isKindOfClass: Person");
    } else {
        NSLog(@"person is't kind of Person");
    }
    if ([man isKindOfClass:[Person class]]) {
        NSLog(@"man isKindOfClass: Person");
    } else {
        NSLog(@"man is't kind of Person");
    }
    if ([obj isKindOfClass:[NSObject class]]) {
        NSLog(@"obj isKindOfClass: NSObject");
    } else {
        NSLog(@"obj is't kind of NSObject");
    }
    
    //类方法
    if ([Person isKindOfClass:[Person class]]) {
        NSLog(@"Person isKindOfClass: Person");
    } else {
        NSLog(@"Person is't kind of Person");
    }
    if ([Man isKindOfClass:[Person class]]) {
        NSLog(@"Man isKindOfClass: Person");
    } else {
        NSLog(@"Man is't kind of Person");
    }
    if ([NSObject isKindOfClass:[NSObject class]]) {
        NSLog(@"NSObject isKindOfClass: NSObject");
    } else {
        NSLog(@"NSObject is't kind of NSObject");
    }
      
}

答案如下:

2020-10-01 21:51:14.241579+0800 ALLWAY-OC[20377:3623321] person isMemberOfClass: Person
person的[self class] 返回 Person == [Person class] 成立
2020-10-01 21:51:14.241655+0800 ALLWAY-OC[20377:3623321] man is't member of Person
man的[self class] 返回 Man == [Person class] 不成立
2020-10-01 21:51:14.241738+0800 ALLWAY-OC[20377:3623321] obj isMemberOfClass: NSObject
obj的[self class] 返回 NSObject == [NSObject class] 成立

2020-10-01 21:51:14.241816+0800 ALLWAY-OC[20377:3623321] Person is't member of Person
Person的ISA是他的元类 所以不成立
2020-10-01 21:51:14.241882+0800 ALLWAY-OC[20377:3623321] Man is't member of Person
Man的ISA是他的元类 所以不成立
2020-10-01 21:51:14.241948+0800 ALLWAY-OC[20377:3623321] NSObject is't member of NSObject
NSObject的ISA是他的元类 所以不成立

2020-10-01 21:51:14.241178+0800 ALLWAY-OC[20377:3623321] person isKindOfClass: Person
person的[self class] 返回 Person == [Person class] 成立
2020-10-01 21:51:14.241265+0800 ALLWAY-OC[20377:3623321] man isKindOfClass: Person
man的[self class] 返回 Man == [Person class] 不成立, 所以循环查找他的父类superClass为Person,所以最终成立
2020-10-01 21:51:14.241343+0800 ALLWAY-OC[20377:3623321] obj isKindOfClass: NSObject
obj的[self class] 返回 NSObject == [NSObject class] 成立

2020-10-01 21:51:14.241436+0800 ALLWAY-OC[20377:3623321] Person is't kind of Person
Person的ISA是他的元类 所以不成立,循环查找他父类NSObject的元类还是不成立
2020-10-01 21:51:14.241494+0800 ALLWAY-OC[20377:3623321] Man is't kind of Person
Man的ISA是他的元类 所以不成立,循环他的父类Person的元类还是不成立,再循环Person的父类NSObject的元类,依旧是不成立的
2020-10-01 21:51:14.241539+0800 ALLWAY-OC[20377:3623321] NSObject isKindOfClass: NSObject
NSObject的ISA是他的元类 所以不成立,所以找NSObject元类的父类为NSObject类,此时tcls == cls成立。

欢迎大家指正!!!

重点是要了解runtime的结构图