使用respondsToSelector会有性能损失

3

我将重构许多旧代码,以使客户端更加强大,能够处理不良服务器响应并在JSON响应具有无效值时记录异常。我考虑使用respondsToSelector来检查正在解析的每个节点的有效性(数据类型)。

我正在检查响应中的数据类型(int,bool等)

[[json objectForKey: @"feature_enabled"] boolValue], 

如果@"feature_enabled"节点的值不是0或1,应用程序将崩溃。

为了解决这个问题,以下是我的做法:

if ([[json objectForKey: @"feature_enabled"] respondsToSelector: @selector(boolValue)]){
          BOOL featureEnabled = [[json objectForKey: @"feature_enabled"] boolValue];
}else{
          Log Exception
}

我没有对这段代码进行任何性能分析,但我想知道如果我打算检查每个JSON响应以解析,那么我应该期望什么样的性能损失。欢迎提供任何信息来源!
2个回答

9

respondsToSelector: 检查是否为 nil。如果不是 nil,则调用 IMP lookUpMethod(Class cls, SEL sel, BOOL initialize, BOOL cache, id inst),该方法从 IMP 缓存中返回方法(使用CacheLookup 宏)。如果未找到,则尝试在类本身中查找方法以填充缓存,这涉及在超类上重复操作。如果失败,则运行forwarding 机制

isKindOfClass: 比较两个类的 isa 指针。如果失败,则重复执行超类,这只是 struct objc_class 中的 'super_class' 字段。

因此,区分两个对象的正确方法是使用isKindOfClass:

请注意,处理 JSON 数据的速度将比上述所有内容慢数千倍。未找到选择器不会使系统停止或任何其他事情发生。


谢谢您的回复,这让我感到很安心。由于我正在检查响应中的数据类型(int、bool等)([[json objectForKey:@"feature_enabled"] boolValue]),如果@"feature_enabled"节点除了0或1之外还有其他内容,那么应用程序就会崩溃。因此,在这种情况下,我的唯一选择是使用-respondsToSelector吗? - Nitin Alabur
1
Apple解析器返回NSString,NSNumber,NSArray,NSDictionary或NSNull。布尔值是NSNumber。如果isKindOfClass:[NSNumber类],则忽略节点,如果通过,则调用boolValue。 - Jano
更正:像 respondsToSelector: 和 isKindOfClass: 这样的方法只查看继承层次结构,而不查看转发链。 - Valentin Shergin

5

您可以考虑使用isKindOfClass方法,我认为这是最佳性能:

if([[yourDictionary objectForKey:@"yourKey"] isKindOfClass:[NSArray class]]) { //假设它是一个数组并处理它 }


2
同意。-isKindOfClass: 只需要检查 Class *isa 指针,而 -respondsToSelector: 可能会执行一些运行时操作。 - Jack Lawrence
3
实际上,-isMemberOfClass: 只会检查 isa。而 -isKindOfClass: 则需要检查所有超类的 isa。 - Catfish_Man
@rooster117,@"Jack Lawrence" 感谢你们的回答。我相信 isKindOfClass 只适用于类(NSArray、NSDictionary、NSString 等),但不能检查特定的数据类型(int、bool 等)。那么在这种情况下,我的唯一选择是使用 -respondsToSelector 吗? - Nitin Alabur
1
int、bool或其他原始类型没有选择器,因为它们不是对象,所以您无法对它们进行检查。您将需要将JSON中的字符串转换为NSNumbers并对其进行检查。 - rooster117

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接