介绍他们之前,首先介绍一个案例
创建一个LSPerson继承自NSObject对象,然后进行如下对比,你猜结果是什么?
[[NSObject class] isKindOfClass:[NSObject class]];
[[LSPerson class] isKindOfClass:[LSPerson class]];
[[NSObject class] isMemberOfClass:[NSObject class]];
[[LSPerson class] isMemberOfClass:[LSPerson class]];
答案是:YES、NO、NO、NO
是否总有一道题出乎你的意料,或者是都出乎意料了?
下面从源码分析问题
首先介绍+class和-class即类方法和对象方法,可以看出他们分别返回类本身和对象的isa,即结果都为其所属类,或为其创建对象的isa
前面也了解到了,对象的isa为其类,类的isa为其元类,他们的关系可以参考 NSObject的实例对象、类对象、元类之间的关系
+ (Class)class {
return self;
}
- (Class)class {
return object_getClass(self);
}
isKindOfClass
然后分别查看isKindOfClass的类方法源码和对象方法源码
通过isKindOfClass的类方法可以得知,是从类的isa开始进行比较的,即元类;从元类开始进行对比指针是否和指定class是否是一个类,然后继续查找父类进行对比,直到父类为nil结束
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = self->ISA(); tcls; tcls = tcls->getSuperclass()) {
if (tcls == cls) return YES;
}
return NO;
}
通过isKindOfClass的对象方法可以得知,是从本类开始进行比较的,即对象的isa;从类开始进行对比指针,是否和指定class是否是一个类,然后继续查找父类进行对比,直到父类为nil结束,这也是我们比较常用的对象所属类的判别
- (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = [self class]; tcls; tcls = tcls->getSuperclass()) {
if (tcls == cls) return YES;
}
return NO;
}
案例1分析:
[NSObject class] 返回的是该类本身,因此调用isKindClass的类方法,即:
+ (BOOL)isKindOfClass:(Class)cls
因此是从NSObject元类开始与指定class(NSObject)进行对比的,第一次使用NSObject元类和其类进行对比,结果不相同,然后找到其父类superClass,根据对象、类、元类之间的关系,可以得知,NSObject的元类的父类是NSObject类,所以此时对比结果返回为YES
案例2分析:
其和案例一相似,是从LSPerson元类开始与指定class(LSPerson)进行对比的,根据对象、类、元类之间的关系,从LSPerson元类开始,向上找到NSObject的元类,再到NSObject都不符合条件,因此返回为false
总结
isKindOfClass当调用对象方法时,是从类开始和指定类进行对比,所以对象调用时一定会属于该类或者其父类
isKindOfClass当使用类调用类方法时,是从其元类和指定类进行对比的,所以比较的是其元类是否属于该元类或者该元类的父类
isMemberOfClass
从源码分别查看其类方法和对象方法
其类方法比较的是元类是否和指定类相同
+ (BOOL)isMemberOfClass:(Class)cls {
return self->ISA() == cls;
}
其对象方法比较的是其类是否和指定类相同
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
案例3、4分别均调用的是isMemberOfClass的类方法,因此比较的是该类的元类是否和其类是否相同,所以返回均为false
总结
isMemberOfClass当调用对象方法时,是其类和指定类进行指针上的对比
isMemberOfClass当使用类调用类方法时,是其元类和指定类进行指针上的对比
案例是class、isMemberOfClass、isKindOfClass、以及类之间的关系的综合考察,一不小心就掉入坑里去了