什么是防止未被识别的选择器'对于从NSDictionary返回的对象

时间:2014-08-27 22:51:55

标签: objective-c

我有以下一些代码,我从服务器获得响应并尝试解析错误消息。

我注意到有时消息对象没有作为NSDictionary类型返回并且会使应用程序崩溃。我想知道最好的做法是什么来防范这种情况?一般来说,我尽量避免执行instanceof检查。同样有选择器检查。感觉应该有一个更好的方法来做这个,而不是明确地检查我被允许使用那些方法/回到我期望的类型。

NSDictionary *message = [serverErrorJSON objectForKey:@"message"];
if (message != nil) {
return [message objectForKey:@"form"];
}

3 个答案:

答案 0 :(得分:4)

if ([serverErrorJSON isKindOfClass:NSDictionary.class]) {
  return serverErrorJSON[@"message"][@"form"];
}

return nil;

在语法和编程上使用文字语法是很好的。

您也不必将它们链接在一起,您可能想要使用JSON的另一个属性,

if ([serverErrorJSON isKindOfClass:NSDictionary.class]) {
  NSDictionary *message = serverErrorJSON[@"message"];
  //...
  return message[@"form"];
}

return nil;

答案 1 :(得分:0)

您的代码:

NSDictionary *message = [serverErrorJSON objectForKey:@"message"];
if (message != nil) {
    return [message objectForKey:@"form"];
}

这里你得到“无法识别的选择器”的原因是[serverErrorJSON objectForKey:@"message"]没有像你期望的那样返回NSDictionary。由于您在该对象上调用objectForKey:,因此建议的处理方法是使用respondsToSelector:包裹该调用:

id message = nil;
if ([serverErrorJSON respondsToSelector:@selector(objectForKey:)]){
    message = [serverErrorJSON objectForKey:@"message"];
    if ([message respondsToSelector:@selector(objectForKey:)]){
        return [message objectForKey:@"form"];
    }
}

这测试您正在调用的选择器(方法)的存在,并且比使用isKindOfClass:之类更安全且更兼容。测试功能而不是类名等总是更好。你不关心对象是否是一个NSDictionary,你关心它是否可以使用你正在调用的方法签名为一个键提供一个对象。

答案 2 :(得分:-1)

防止无法识别的选择器错误的最佳方法是根据您的使用情况检查respondsToSelectorisKindOfClass

不幸的是,如果您发现自己需要经常验证某个对象是字典,那么您的代码会变得非常混乱,这种情况可能会出现在您的情况下,就像您的数据结构中嵌套字典一样。

您可以通过添加类别来清理:

@interface NSDictionary (Safe)

//Returns objectForKey if dictionary param is valid, else returns nil
+ (id) _safeObjectForKey: (NSString*) key
                    dict: (NSDictionary*) dictionary;

@end

@implementation NSDictionary (Safe)

+ (id) _safeObjectForKey:(NSString *)key
                    dict:(NSDictionary *)dictionary {

    if ([dictionary isKindOfClass:[NSDictionary class]]) {
        return [dictionary objectForKey:key];
    }
    return nil;

}

@end

然后使用它,给出你的例子:

NSDictionary *message = [NSDictionary _safeObjectForKey: @"message"
                                                   dict: serverErrorJSON];
return [NSDictionary _safeObjectForKey:@"form"
                                  dict:message];

您也可以为其他常见的无法识别的选择器错误生成器执行类似的操作,例如NSArray的objectAtIndex等。