返回
坑点 1:
坑点 2:
isKindOfClass的源码坑
IOS
2023-11-16 11:16:55
iOS底层实验室
在iOS开发中,isKindOfClass
方法是用来判断一个对象是否属于某个类的实例。它经常被用于类型检查和类型转换。然而,如果开发者不熟悉ISA
和Class
等底层概念,那么在使用isKindOfClass
时很容易踩坑。
本篇文章将深入探讨isKindOfClass
的源码,揭示隐藏的坑点,并提供避免这些坑点的建议。
isKindOfClass
的源码
isKindOfClass
方法的源码位于objc/runtime.h
头文件中,如下所示:
BOOL isKindOfClass(id obj, Class cls)
其中:
obj
是要检查的对象。cls
是要比较的类。
该方法的实现非常简单:
BOOL isKindOfClass(id obj, Class cls) {
return obj->isa == cls;
}
从源码可以看出,isKindOfClass
通过比较对象的ISA
指针和目标类的指针来确定对象是否属于该类。ISA
指针指向对象的类对象,它存储了对象的类型信息。
坑点 1:ISA
指针的改变
第一个坑点是ISA
指针的改变。在某些情况下,对象的ISA
指针可能会被改变,导致isKindOfClass
的判断结果不准确。例如:
// 创建一个NSObject对象
NSObject *obj = [[NSObject alloc] init];
// 修改对象的ISA指针
object_setClass(obj, [NSString class]);
// 判断对象是否属于NSString类
BOOL isNSString = [obj isKindOfClass:[NSString class]];
在这种情况下,object_setClass
函数将obj
的ISA
指针修改为NSString
类的指针。因此,isKindOfClass
将返回YES
,即使obj
实际上是一个NSObject
对象。
坑点 2:Class
的嵌套
第二个坑点是Class
的嵌套。在Objective-C中,类可以嵌套在其他类中。例如:
// 创建一个嵌套类
@interface OuterClass : NSObject
{
// InnerClass作为OuterClass的一个成员变量
InnerClass *_innerClass;
}
@end
@interface InnerClass : NSObject
@end
在这种情况下,InnerClass
是一个嵌套在OuterClass
中的内部类。如果使用isKindOfClass
来判断一个InnerClass
对象是否属于OuterClass
类,则结果将为NO
:
// 创建一个InnerClass对象
InnerClass *innerClass = [[InnerClass alloc] init];
// 判断对象是否属于OuterClass类
BOOL isOuterClass = [innerClass isKindOfClass:[OuterClass class]];
这是因为InnerClass
对象的ISA
指针指向InnerClass
类,而不是OuterClass
类。
避免坑点的建议
为了避免isKindOfClass
的坑点,建议开发者遵循以下建议:
- 谨慎修改
ISA
指针。 仅在特殊情况下才修改对象的ISA
指针。 - 理解
Class
的嵌套。 注意类嵌套可能会导致isKindOfClass
的判断结果不准确。 - 使用其他类型检查方法。 如果需要更准确的类型检查,可以考虑使用
conformsToProtocol
或isMemberOfClass
方法。