NSDictionary扩展了valueForKey方法

时间:2014-03-07 17:03:05

标签: ios

我是否可以创建扩展- (id)valueForKey:(NSString *)key方法的类别,如果此键的值相等[NSNull null],则会返回空字符串@""

它连接到我在JSON中从后端服务器获得的某些键的nil值。

因此,如果我需要为属性保存一些值,它可以是nil。

假设我使用此代码的值为key nil

artist.name = ad[@"artist"][@"name"]; // nil value on the right.

因此,如果我有扩展程序,则会检查密钥值并返回@"" nil的意图。这是否有意义。

或者我是否需要扩展NSManagedObject来检查属性类型,然后返回相应的值@""0nil0.0f另一种不是字符串类型。

4 个答案:

答案 0 :(得分:2)

您可以在NSDictionary上定义一个类别,然后在那里进行转换,而不是在NSObject上定义类别:

@interface NSObject (DBNullHandling)
-(NSString*)nullToEmpty;
@end

@implementation NSObject (DBNullHandling)
-(id)nullToEmpty {
    return (self == [NSNull null]) ? @"" : self;
}
@end

现在你可以这样做:

artist.name = [ad[@"artist"][@"name"] nullToEmpty];

如果ad[@"artist"][@"name"]返回[NSNull null]artist.name会被分配@"";否则,它将被赋予ad[@"artist"][@"name"]返回的值。

答案 1 :(得分:1)

我建议您检查密钥是否存在,而不是将NSDictionary子类化以更改valueForKey:的实现。所以你会这样做:

BOOL keyExistsInDictionary = [[myDict allKeys] containsObject:key];
id objectForKey = [myDict objectForKey:key];
if (nil == objectForKey && keyExistsInDictionary) objectForKey = @"";

如果objectForKey:返回nil,您可以检查keyExistsInDictionary以查看密钥是否存在且只包含[NSNull null]。这使您可以区分存在的密钥和不修改NSDictionary的密钥。

答案 2 :(得分:1)

我所做的是在执行作业之前进行检查。三方运营商是一个很好的速记方式。你有:

artist.name = ad[@"artist"][@"name"];

相反,我会写

id val = ad[@"artist"][@"name"];
artist.name = val ? val : @""; // or val ?: @""

(我还没有完全理解这个问题,因此可能有必要将检查分解为更多阶段或以某种方式修改它以检查[NSNull null]而不是nil。但是你明白了。)

答案 3 :(得分:1)

  

我可以创建将扩展的类别 - (id)valueForKey:(NSString *)key method

这里简短的回答是不,不要那样做。类别允许您通过添加方法扩展类,但不应使用它们来覆盖现有方法。这样做的主要原因是它不可靠 - 类别中的方法添加到类中的顺序没有定义,这意味着如果你有两个类别覆盖相同的方法,你就不知道哪个该类最终将最终得到的方法的版本。

另一个原因是您无法从覆盖方法引用原始方法,因此您必须重新实现要保留的行为。

最后,类别会更改类,因此该类的每​​个实例都将具有新行为。当您添加方法时,这通常不是问题 - 不使用新方法的代码不受新功能的影响。但是,当您更改现有方法时,尤其是对于NSDictionary广泛使用的类时,您很可能会破坏大量现有代码。

  

如果此键的值相等[NSNull null],它将返回空字符串@“”

你已经得到了一些好的答案,但是既然你问过类别,这里有一种方法可以恰当地使用一个类别来解决问题。不要尝试更改-valueForKey:,而是使用类别添加一个名为-stringForKey:的新方法,该方法返回一个字符串。听起来你只是在使用字符串,所以这似乎是一个合理的解决方案。实现可以调用-valueForKey:并将非字符串对象转换为字符串:

@interface NSDictionary (StringValue)
- (NSString *)stringForKey:(NSString*)key;
@end

@implementation NSDictionary (StringValue)
- (NSString *)stringForKey:(NSString*)key
{
    id value = [self valueForKey:key];
    NSString *string;
    if ([value isKindOfClass:[NSString class]]) {
        string = (NSString*)value;
    }
    else if ([value isKindOfClass:[NSNull class]]) {
        string = @"";
    }
    else {
        string = [value description];
    }
    return string;
}
@end