2011-08-11 121 views
13

我没有搜索如何检查NSDictionary密钥是否存在,并提出了解决方案。但是它仍然给我一个错误,说为键添加空值。 我不确定我的代码是否正确。如果任何人有任何想法可以帮助我。检查NSDictionary中是否存在密钥

NSDictionary *result; 
id myImageURL = [result objectForKey:@"url"]; 
if ((NSNull *)myImageURL == [NSNull null]) 
    myImageURL = @""; 

id myImage = [result objectForKey:@"image"]; 
if ((NSNull *)myImage == [NSNull null]) 
    myImage = @""; 

检查是否为空添加任何东西,如果没有添加值。但它仍然给我一个错误,不知道为什么。

/****OUTPUT*****/ 

2011-08-11 14:56:06.668 Tab_Table_Win[6510:207] RESULTS : { 
image = "<UIImage: 0xbc332c0>"; 
url = "http://a3.twimg.com/profile_images/999228511/normal.jpg"; 
} 

2011-08-11 14:56:06.669 Tab_Table_Win[6510:207] url : http://a3.twimg.com/profile_images/999228511/normal.jpg 
2011-08-11 14:56:06.670 Tab_Table_Win[6510:207] IMage : <UIImage: 0xbc332c0> 

/*****Breaks Here ***/ 

2011-08-11 14:56:06.876 Tab_Table_Win[6510:207] RESULTS : { 
} 
2011-08-11 14:56:06.878 Tab_Table_Win[6510:207] url : (null) 
2011-08-11 14:56:06.879 Tab_Table_Win[6510:207] IMage : (null) 
2011-08-11 14:56:06.881 Tab_Table_Win[6510:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary setObject:forKey:]: attempt to insert nil key' 
+0

它给出的精确错误是什么,以及哪一行代码? – Chuck

+0

我上面编辑了我的代码。 – lifemoveson

+0

检查我的答案。通过发送它到一个id然后铸造它,你正在浪费记忆,尽管非常低。你可以做到一行。我希望iOS有一个像.net这样的keyExist属性。 –

回答

2
NSDictionary *result; 
NSString *myImageURL = [result objectForKey:@"url"]; 
if (myImageURL == NULL) 
    myImageURL = @""; 

NSString *myImage = [result objectForKey:@"image"]; 
if (myImageURL == NULL) 
    myImage = @""; 

其是否正常工作,而不是在得太多NULL类。

+0

没有。我做了NSLog,并得到了这个答案:result:{ }然后它中断。不知道什么是错的呢? – lifemoveson

+0

你在myImageURL上做了一个NSLog?在检查null之前?我可能会检查前后。 NSLog(@“result:%@”,[result objectForKey:@“url”]); NSLog(@“myImageURL:%@”,myImageURL); –

6

每当我尝试检查,如果从字典中被返回的对象为null,我这样做:

id obj = [myDictionary objectForKey:entityKeyName]; 
if (obj == [NSNull null]) { 
    // do something 
} 
在你的代码

然后,这将是:

NSDictionary *result; 
NSString *myImageURL = [result objectForKey:@"url"]; 
if (myImageURL == [NSNull null]) 
    myImageURL = @""; 

这就是我会在你的代码中做。

此外,只要确定,是否定义了NSDictionary结果?在你的代码中,它没有任何设置。它只是被定义为您计划使用的变量,称为结果

+0

你需要与NSNull的任何NSString种姓。 – lifemoveson

4

如果某个键的对象不存在,NSDictionary将返回nil。一个NSNull是一个实际的对象,因此是一个独特的事物。这就像能够记录存在价值和价值为空的区别,而不是记录是否存在价值。它也稍微偏离了你用C语言指向一个对象的指针而不仅仅是一个对象的方向,所以从这个角度来看它并不完全符合语义。

在Objective-C中,您可以发送任何消息到nil,结果保证是nil(或0)。因此,如果您的代码旨在确保您拥有安全的对象引用,就像您在C++中所做的那样,那么您所做的就没有必要了。复合语句,如:

object = [[Type alloc] init]; 

始终是明确的安全,即使ALLOC失败并返回nil。所发生的只是对init的呼叫根本不会做任何事情,并且对象将以值nil结束,因为发送initnil的结果也是nil

这就是说,Bill和Emmanuel提供的答案应该是正确的。将您的结果直接与nil比较,或者直接将其与零比较。如果您稍后发生崩溃,我想这是因为您期望myImageUrlmyImageNSString(我注意到您在原始代码中使用了无类型的id)以外的类型,并向它们发送消息不回应。

13

正确答案是:

NSDictionary *result; 
NSURL *myImageURL = [result objectForKey:@"url"]; 
UIImage *myImage = [result objectForKey:@"image"]; 

/**** Correct way ****/ 
if (myImageURL != nil && myImage != nil) { 
    [images setObject:myImage forKey:myImageURL]; 
} 

谢谢所有的解释。

+1

你能解释一下吗? – lifemoveson

2

这另一种选择:

if (![result objectForKey:@"image"]) 
    { 
     NSLog(@"doesn't exist"); 
    } 
    if ([result objectForKey:@"image"]) 
    { 
     NSLog(@"exist"); 
    } 
1

,这不是为我工作,我理解了它这样

id myImageURL = [result objectForKey:@"url"]; 
if ([myImageURL isKindOfClass:[NSNull class]]) 
    myImageURL = @""; 
1

好吧,这里是一个实际的答案,@Iomec几乎有

UIImage *myImage = ([result objectForKey:@"image"] != [NSNull null] ? [result objectForKey:@"image"] : nil); 

这是实际的正确答案,因为它会为空,当你说myImage = [receivedObject ...];那么如果myImage = nil,你实际上将一个空值(nil)转换成一个异常的类,如果不是正在运行的bug。

您应该: 1)测试NSNull空值 2)如果不是零然后分配

如果代码没有窃听出来呢,它会在生产时,你有8个应用程序在后台运行一天。

0

我得到了与JSONKit相同的问题。那里的实现有

- (id)objectForKey:(id)aKey 
{ 
    [...] 
    return((entryForKey != NULL) ? entryForKey->object : NULL); 
} 

所以如果对象不存在,这肯定会返回NULL。我检查它像下面

NSArray* array = [myDictionary objectForKey:@"a"]; 
if((NSNull*)arrays!=[NSNull null]) 
{ 
    [...] 
} 
7

回答以下工作对我来说:

https://stackoverflow.com/a/2784675/936957

if ([dictionary objectForKey:key]) { 
    // previously stored data for "key" 
} 

另外请注意,您可以通过获得在字典中排列键的

[dictionary allKeys] 
+0

这是最好的答案,如果字典甚至没有密钥,就不需要变量。将它设置在if语句中。 +1 –

+0

这看起来像会起作用,但它不会。如果存在NSNull,objectForKey仍然返回true – quantumpotato

+0

@quantumpotato,NSDictionary:objectForKey:返回nil,如果该键不存在于字典中,请参见[NSDictionary的类引用](https://developer.apple.com/library/) mac/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class /#// apple_ref/occ/instm/NSDictionary/objectForKey :)。尽管如此,我已经测试过它,似乎没有问题。 –

11

汤米完美地解释了这一点。

我建议是建立像NSDictionary的一个扩展类:

#import <Foundation/Foundation.h> 

@interface NSDictionary (Safety) 

- (id)safeObjectForKey:(id)aKey; 

@end 

和实现文件:

#import "NSDictionary+Safety.h" 

@implementation NSDictionary (Safety) 

- (id)safeObjectForKey:(id)aKey { 
    NSObject *object = self[aKey]; 

    if (object == [NSNull null]) { 
    return nil; 
    } 

    return object; 
} 

@end 

,而不是在代码中使用[dictionary objectForKey:@"keyName"];而且,使用

[dictionary safeObjectForKey:@"keyName"]; 

这样,如汤米解释,你会发送一个方法调用一个无wh我不会崩溃的应用程序,但你的对象会得到一个零值。

希望这会有所帮助。

0
 1. Results Dictionary after JSON parsing: 

     //if hits success 

     {"result":{"action":"authentication","statusCode":"200","statusMsg":"No 
     error, operation 
     successful.","count":1,"data":{"apiToken":"509e6d21-4f69-4ded-9f3d-4537e59e6a3a","userId":8,"role":"Bidder","firstName":"bidder","lastName":"bidder","emailAddress":"[email protected]","countiesCovered":"21,16,11,1,2,14,32,3,4,25,13,15,5,41,43,6,12,7,24,39,17,36,42,44,29,40,8,18,19,27,9,28,23,10,33,26,35,20,30,22,34,31"}}} 

//Data is Dictionary inside Result 


----------------------------------------------------------------------- 
      I had an error showing : NULL DATACould not cast value of type 'NSNull' (0xda7058) to 'NSDictionary' (0xda6d74) and the result was 
     the following. 

      ({"result":{"action":"authentication","statusCode":"204","statusMsg":"Invalid 
     Username or Password","count":null,"data":null}}) 

      I fixed the Null check of dictionary. 

           if (result.objectForKey("data") is NSNull) 
           { 
      print ("NULL DATA") 

           } 
           else 
           { 
            let data = result["data"]as! NSDictionary 
            print (data) 

           } 
0

可能希望通过检查以确保它不是字符串而不是检查它是否为零来增加更多的安全性。 (以确保它不是数字或其他任何你可能不想要的东西)。

id myImageURL = [result objectForKey:@"url"]; 
if (![myImageURL isKindOfClass:[NSString class]]) { 
    myImageURL = @""; 
}