isKindOfClass:和isMemberOfClass的用
2018-09-29 本文已影响0人
Gxdy
本文将从NSObject源码的角度来讲述isKindOfClass和isKindOfClass使用.
如需要查看更多更新源码资源请前往苹果官方源码下载
在进入正文之前先附上一张isa与superclass指针的指向结构图
isa与superclass.png
- isKindOfClass:(实例方法)
- NSObject源码实现如下
- (BOOL)isKindOfClass:(Class)cls {
// 循环遍历直到匹配到对应class或者tcls==nil
// (从上图可以知道tcls->superclass最终会指向nil)
for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
-
分析:从源码可以知道
- isKindOfClass: 实例对象方法会先通过isa找到调用者(实例对象)的类对象进行判断。如果tcls == cls,就结束遍历返回YES。如果tcls != cls,就会沿着superclass指向的方向寻找父类的类对象,直到条件成立或者tcls=nil。 -
结论:通过
实例对象访问- isKindOfClass:方法,判断的是实例对象的类对象或者父类的类对象是否等于cls(传入的参数) -
如:
UIView *view = [[UIView alloc] init];
[view isKindOfClass: [UIView class]]; // --> YSE
[view isKindOfClass: [NSObject class]]; // --> YSE
+ isKindOfClass:(类对象方法)
- NSObject源码实现如下
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
-
分析:
- 首先,源码中
tcls初始 值是object_getClass((id)self),这是一个元类对象。 - 之后
tcls = tcls->superclass,任然是一个元类对象,之后又成NSObject的类对象,最后是nil(从上图可知元类对象的superclass --> SuperClass的元类对象 --> RootClass的元类对象 --> NSObject的类对象 --> nil)。
- 首先,源码中
-
结论:通过实例对象访问
+ isKindOfClass:方法,判断的是类对象的元类对象或者父类的元类对象或者NSObject的类对象是否等于cls(传入的参数) -
如:
[UILabel isKindOfClass: [UILabel class]]; // --> NO,元类对象 != [UILabel class](类对象)
[UILabel isKindOfClass: object_getClass([UILabel class])]; // --> YSE
[[UILabel class] isKindOfClass: object_getClass([UILabel class])]; // --> YSE
[[UILabel class] isKindOfClass: object_getClass([UIView class])]; // --> YSE
[[UILabel class] isKindOfClass: object_getClass([NSObject class])]; // --> YSE
[[UILabel class] isKindOfClass: [NSObject class]]; // --> YSE
- isMemberOfClass:(实例方法)
- NSObject源码实现如下
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
- 源码可知:判断的是
类对象是否等于cls - 如:
[[UILabel new] isMemberOfClass:[UILabel class]]; // YES
[[UILabel new] isMemberOfClass:[UIView class]]; // NO
+ isMemberOfClass:(类对象方法)
- NSObject源码实现如下
+ (BOOL)isMemberOfClass:(Class)cls {
return object_getClass((id)self) == cls;
}
- 源码可知:判断的是
类对象的元类对象是否等于cls - 如:
[UILabel isMemberOfClass:[UIView class]]; // NO
[UILabel isMemberOfClass:object_getClass([UILabel class])]; // YES
- 总结
- 不管是
isKindOfClass还是isMemberOfClass
- 在
类对象调用时,都是与调用者的元类对象与传入参数进行判断; - 在
实例对象调用时,不管是isKindOfClass还是isMemberOfClass,都是与调用者的类对象与传入参数进行判断;
-
isKindOfClass具有继承关系,会沿着superclass遍历;isMemberOfClass,则没有继承关系,只会判断一次
3.注意点与用法:
- 要注意
类对象调用时,判断的是元类对象 - 要注意
[NSObject class]在+ isKindOfClass中的特殊性 - 要注意
isKindOfClass是有继承关系 - 判断某个对象是什么类(
忽略继承)时,尽量用isMemberOfClass - 判断某个对象是继承自什么类(
包含继承)时,用isKindOfClass