isMemberOfClass:
与isKindOfClass:
其实在平常的开发中,用的还是比较多的,今天从底层来分析他的实现究竟是什么样的以及需要注意的点
1、 isKindOfClass
分为类方法和实例方法
- (BOOL)isKindOfClass:(Class)cls
+ (BOOL)isKindOfClass:(Class)cls
先看看源码
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = object_getClass((id)self); 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;
}
类方法是对cls的元类/根元类的父类进行递归
实例方法是对cls的父类进行递归
关于元类、根元类以及父类的走向, 可以参照isa探索
代码示例
前提: Person:NSObject ------ Student:Person
代码:
//类方法
BOOL kindObj = [[NSObject class] isKindOfClass:[NSObject class]]; //1
BOOL kindPer = [[Person class] isKindOfClass:[NSObject class]]; //2
BOOL kindStu = [[Student class] isKindOfClass:[NSObject class]];
BOOL kindTemp = [[Student class] isKindOfClass:[Person class]]; //3 *这个分析请注意⚠️
NSLog(@"kindObj = %@ kindPer = %@ kindStu = %@ kindTemp = %@",@(kindObj),@(kindPer),@(kindStu),@(kindTemp));
打印结果:
kindObj = 1 kindPer = 1 kindStu = 1 kindTemp = 0
//实例方法
BOOL iskindStu = [[Student new] isKindOfClass:[Student class]];
BOOL iskindPer = [[Student new] isKindOfClass:[Person class]];
BOOL iskindObj = [[Student new] isKindOfClass:[NSObject class]]; //4
NSLog(@"iskindStu = %@ iskindPer = %@ iskindObj = %@",@(iskindStu),@(iskindPer),@(iskindObj));
打印结果:
iskindStu = 1 iskindPer = 1 iskindObj = 1
我们来参照isa走向图和源码来分析为什么打印结果是这样的
1、
[[NSObject class] isKindOfClass:[NSObject class]];
这个之所以打印为1 并不是我们想象的左右两边一样,所以打印1,而是因为NSObject的更元类的父类是NSObject本身
分析:
[object_getClass((id)self)] 意思是 [NSObjet class] 的元类,在图中 就是 root class (class) 的isa 指向的是 root class(meta)
root class(meta)的父类 是 root class (class)
2、[[Student class] isKindOfClass:[NSObject class]];
分析:
[object_getClass((id)self)] 的 superclass 依次是:Subclass(meta) -> Superclass(meta) -> root class(meta) -> root class(class)
在这里 isKindOfClass:[NSObject class] 就是 root class(class)
3、[[Student class] isKindOfClass:[Person class]];
分析:
[object_getClass((id)self)] 的 superclass 依次是:Subclass(meta) -> Superclass(meta) -> root class(meta) -> root class(class)
在这里 isKindOfClass:[Person class] 是 Superclass(class),这个过程中 ,都没有指向Superclass(class),所以返回的是NO
4、[[Student class] isKindOfClass:[Person class]];
实例方法很好理解
分析:
Student 继承Person Person 继承NSObject,所以 [Student new] 的父类是Person ,父类的父类是 NSObject,所以结果都是1
2、isMemberOfClass
分为类方法和实例方法
- (BOOL)isMemberOfClass:(Class)cls
+ (BOOL)isMemberOfClass:(Class)cls
先看看源码
+ (BOOL)isMemberOfClass:(Class)cls {
return object_getClass((id)self) == cls;
}
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
isMemberOfClass相对于isKindOfClass来说,只是做了一层判断,而没有递归
代码示例
前提: Person:NSObject ------ Student:Person
代码:
//类方法
BOOL memObj = [[NSObject class] isMemberOfClass:[NSObject class]];
BOOL memPer = [[Person class] isMemberOfClass:[NSObject class]];
BOOL memStu = [[Student class] isMemberOfClass:[NSObject class]];
BOOL memTemp = [[Student class] isMemberOfClass:[Person class]]; //1
NSLog(@"memObj = %@ memPer = %@ memStu = %@ memTemp = %@",@(memObj),@(memPer),@(memStu),@(memTemp));
打印结果:
memObj = 0 memPer = 0 memStu = 0 memTemp = 0
//实例方法
BOOL isMemStu = [[Student new] isMemberOfClass:[Student class]];
BOOL isMemPer = [[Student new] isMemberOfClass:[Person class]];
BOOL isMemObj = [[Student new] isMemberOfClass:[NSObject class]]; //2
NSLog(@"iskindStu = %@ iskindPer = %@ iskindObj = %@",@(iskindStu),@(iskindPer),@(iskindObj));
打印结果:
isMemStu = 1 isMemPer = 0 isMemObj = 0
1、[[Student class] isMemberOfClass:[Person class]]
分析: object_getClass((id) [Student class]) 得到的是 Subclass(meta) ,是根元类,所以打印结果都是NO
2、[[Student new] isMemberOfClass:[Person class]]
分析:
object_getClass((id) [Student new]) 得到的是 Subclass(class) , 在上面的类方法示例中,只有[Student class] 是 Subclass(class),所以其他都是NO。
3、 注意事项:
1、对于 isKindOfClass 的类方法和示例方法,理解起来稍微不同,不过知道了isa走向图和源码,就可以分析出来为什么了。
BOOL kindObj = [[NSObject class] isKindOfClass:[NSObject class]];
BOOL kindTemp = [[Student class] isKindOfClass:[Student class]];
打印结果为什么一个是YES,一个是NO,isKindOfClass基本就理解透了
比如 [[Student class] isKindOfClass:[NSObject class]]; 之所以打印结果是YES,是由于 NSObject的元类的父类 指向的是NSObject class 本身
2、类族
BOOL ismem = [[NSMutableArray new] isMemberOfClass:[NSArray class]]; 的结果是NO,虽然NSmutableArray 是继承 NSArray,但是需要了解的一个概念:类族;可自行Google。
类族包括:NSString、 NSArray、NSDictionary 、NSData、NSNumber等
网友评论