NSDictionary stringForKey:并将[NSNull null]强制转换为NSString *

时间:2010-07-18 01:39:29

标签: iphone objective-c

我最近被告知将[NSNull null]投射到(NSString*)是“可怕的”。

但是,如果密钥不在字典中,-[NSDictionary stringForKey:]方法将返回[NSNull null],如果我不进行强制转换,编译器会对我大喊大叫。

我错过了什么吗?

编辑:

我的错误......我想我可能会开始看到这个问题......

正如大家所指出的那样,NSDictionary上没有stringForKey:方法,是的,当我问这个问题时我正在考虑用户默认值...所以我回去看看我在做什么......这是:

NSString * someValue = (NSString*)[myDictionary objectForKey:@"key"];
if (someValue == (NSString*)[NSNull null]) ...

如果我在这种情况下不进行演员表,我会收到以下错误:

warning: comparison of distinct Objective-C types 'struct NSNull *' and 'struct NSString *' lacks a cast

施放值“解决”了问题,我宁愿不写10行,其中一行会做...

这不好吗?我会在哪里遇到问题?

另外:

字典来自JSON库...在这种情况下,NULL是有效值,因此,如果缺少密钥,可能不是NSDictionary返回它们,而是密钥实际上是在那里,并且该值实际上为空。

5 个答案:

答案 0 :(得分:14)

NSDictionary不会返回NSNull的实例,除非您或其他来源将它们放在那里。同样,NSDictionary也不会回复-stringForKey:。您是否在考虑NSUserDefaults

如果您有一个NSDictionary的实例,而您想要做的就是从中获取一个字符串,您可以尝试类似下面的代码。

NSString *MyGetString(NSDictionary *dict, id key, NSString *fallback) {
    id result = [dict objectForKey: key];

    if (!result)
        result = fallback;
    else if (![result isKindOfClass: [NSString class]])
        result = [result description];

    return result;
}

将后备字符串作为fallback传递 - 如果没有对象与键key相关联,函数将使用该字符串。

答案 1 :(得分:7)

正如Jonathan的代码所示,如​​果你使用isKindOfClass:方法会更好。即使您更改了检索对象的方法等,它也会保护您,并且是一种更准确的检查。

另请注意,[someValue isKindOfClass:[NSString class]]仅在YES不是someValue并且nil时返回NSString,这意味着它也足以进行nil }值。

答案 2 :(得分:6)

演员阵容“糟糕”,因为NSNull 不是 NSString。转换不会改变指向的对象的实际类型,它只会改变编译器的,嗯,态度

在所示的非常特殊的情况下,你将要对象执行的事情是对指针平等的直接测试,你的方法将起作用,但它是潜在未来的来源错误。这种使编译器警告变得沉默的hacky会让人感到不安,如果有更好的方法,应该避免使用。

当然,真正的问题是之前的演员表,其中来自NSObject*的{​​{1}}直接投放到objectForKey:而没有问题。目前你可以逃脱它,因为你认为你只能得到字符串或NSString*,但是如果JSON库发生变化或者只是不履行合同会发生什么?你最好做一些像:

NSNull

答案 3 :(得分:3)

您可以使用此类别扩展来包装此逻辑。 它在github上

的NSDictionary + Verified.h

//  NSDictionary+Verified.h
//
//  Created by alexruperez on 08/05/13.
//  Copyright (c) 2013 alexruperez. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface NSDictionary (Verified)

- (id)verifiedObjectForKey:(id)aKey;

@end

的NSDictionary + Verified.m

NSDictionary+Verified.m

#import "NSDictionary+Verified.h"

@implementation NSDictionary (Verified)

- (id)verifiedObjectForKey:(id)aKey
{
    if ([self objectForKey:aKey] && ![[self objectForKey:aKey] isKindOfClass:[NSNull class]]) return [self objectForKey:aKey];
    return nil;
}

@end

答案 4 :(得分:1)

对NULL检查的一个很好的测试,特别是在测试网络API(特别是JSON)的解析结果时,是isEqual:方法。我使用...测试存在和可用值

NSString *someValue = [response objectForKey:MyAPIKeySomeValue];
if (!!someValue && ![someValue isEqual:[NSNull null]]) {
    // optionally test for class type
    // use someValue
}
else {
    // error out for required values; skip for optional values
}

更一般地说,如果您期望特定格式的JSON,并且API不符合该要求,您可以考虑将@try/@catch包裹起来。然后,您可以处理异常/非法响应格式,并消除无效数据格式的硬崩溃。

如果格式定义松散,您可以通过构建有意义的NSError来让您的解析例程更加优雅地失败。