1、面试题
以下代码打印结果是什么?
NSLog(@"%d",[Person isMemberOfClass:[Person class]]);NSLog(@"%d",[Person isKindOfClass:[Person class]]);NSLog(@"%d",[NSObject isMemberOfClass:[NSObject class]]);NSLog(@"%d",[NSObject isKindOfClass:[NSObject class]]);
想要知道打印结果,需要先知道isMemberOfClass:和isKindOfClass:的底层原理。
2、isMemberOfClass:和isKindOfClass:对象方法
查看 objc源码(NSObject.mm):
- (BOOL)isMemberOfClass:(Class)cls {return [self class] == cls;}- (BOOL)isKindOfClass:(Class)cls {for (Class tcls = [self class]; tcls; tcls = tcls->getSuperclass()) {if (tcls == cls) return YES;}return NO;}
由源码可知:
-isMemberOfClass:是用于判断receiver是否是传入的cls类。
-isKindOfClass:是用于判断receiver是否是传入的cls类或cls类的子类。
例如创建一个Person类继承于NSObject,进行如下判断:
Person *person = [[Person alloc] init];NSLog(@"%d",[person isMemberOfClass:[Person class]]);NSLog(@"%d",[person isMemberOfClass:[NSObject class]]);NSLog(@"%d",[person isKindOfClass:[NSObject class]]);NSLog(@"%d",[person isKindOfClass:[Person class]]);
打印结果:
~: 1~: 0~: 1~: 1
3、isMemberOfClass:和isKindOfClass:类方法
查看 objc源码 :
+ (BOOL)isMemberOfClass:(Class)cls {return self->ISA() == cls;}+ (BOOL)isKindOfClass:(Class)cls {for (Class tcls = self->ISA(); tcls; tcls = tcls->getSuperclass()) {if (tcls == cls) return YES;}return NO;}
由源码可知:
+isMemberOfClass:是用于判断receiver的元类是否是传入的cls元类
+isKindOfClass:是用于判断receiver是否是传入的cls元类类或cls元类的子类。
例如创建一个Person类继承于NSObject,进行如下判断:
NSLog(@"%d",[Person isMemberOfClass:[Person class]]);NSLog(@"%d",[Person isKindOfClass:[Person class]]);NSLog(@"%d",[Person isMemberOfClass:object_getClass([Person class])]);NSLog(@"%d",[Person isKindOfClass:object_getClass([Person class])]);NSLog(@"%d",[Person isKindOfClass:[NSObject class]]);
打印结果:
~: 0~: 0~: 1~: 1~: 1
上面两个判断结果是0,因为类方法判断传入的应该是元类,[Person class]是类对象,所以结果是0。
但是有个比较特殊的情况,NSObject元类的superclass指针指向的是NSObject的类对象(可参考:isa、superclass),所以类方法isKindOfClass传入[NSObject class]结果是YES。
4、总结
在了解isMemberOfClass和isKindOfClass的原理后,就可以确定以下代码打印结果
NSLog(@"%d",[Person isMemberOfClass:[Person class]]);NSLog(@"%d",[Person isKindOfClass:[Person class]]);NSLog(@"%d",[NSObject isMemberOfClass:[NSObject class]]);NSLog(@"%d",[NSObject isKindOfClass:[NSObject class]]);
打印结果:
~: 0~: 0~: 0~: 1
分析:
第一行和第二行:传入的参数[Person class],是类对象,receiver是Person的类对象,遍历receiver的元类和元类的父类不会找到[Person class]类对象,所以返回结果是NO。
第三行和第一行、第二行原理相同。
第四行:传入参数是[NSObject class],是类对象,receiver是NSObject的类对象,遍历receiver的元类和元类的父类,会找到[NSObject class]对象,所以返回结果是YES。
