【问题标题】:Check if key exists in NSDictionary is null or not检查 NSDictionary 中是否存在键是否为空
【发布时间】:2011-08-11 19:28:30
【问题描述】:

我确实搜索了如何检查 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 = @"";

检查 null 是否不添加任何内容,如果不添加值。但它仍然给我一个不知道为什么的错误。

/****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'

【问题讨论】:

  • 它给出的确切错误是什么,以及哪一行代码?
  • 检查我的答案。通过将其发送到 id 然后将其转换为您正在浪费内存,尽管它非常低。你可以做一行。我希望 iOS 有一个类似 .net 的 keysExist 属性。

标签: iphone objective-c nsstring nsdictionary


【解决方案1】:

正确答案是:

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

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

谢谢大家的解释。

【讨论】:

  • 你能解释一下吗?
【解决方案2】:

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

我建议创建 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"];

这样,正如 Tommy 解释的那样,您将向 nil 发送一个方法调用,这不会使应用程序崩溃,但您的对象将获得一个 nil 值。

希望这会有所帮助。

【讨论】:

    【解决方案3】:

    每当我尝试检查从字典返回的对象是否为空时,我都会这样做:

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

    然后在您的代码中,它将是:

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

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

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

    【讨论】:

    • 你需要对任何 NSString 使用 NSNull 进行种姓。
    【解决方案4】:

    下面的答案对我有用:

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

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

    另请注意,您可以使用以下方法获取字典中的键数组

    [dictionary allKeys]
    

    【讨论】:

    • 这是最好的答案,如果字典甚至没有键,就不需要一个变量。在 if 语句中设置它。 +1
    • 这看起来可行,但实际上并没有。如果存在 NSNull null,objectForKey 仍然返回 true
    • @quantumpotato, NSDictionary:objectForKey: 返回 nil,如果字典中不存在该键,请参阅 Class reference for NSDictionary 。不过,我已经测试过了,似乎没有问题
    • 嗯,有一个变量来避免在里面重复 [dictionary objectForkey:key] 是很好的。字典[@"key"] 与 key 的对象相同,是吗?
    • @quantumpotato,是的,我同意
    【解决方案5】:

    如果某个键的对象不存在,NSDictionary 将返回nilNSNull 是一个实际的对象,因此是一个独特的东西。这就像能够记录有值和值为空的值与不记录是否有值之间的区别。它还取决于您用 C 语言来思考指向对象的指针的间接性,而不仅仅是一个对象,因此从这个角度来看,它在语义上并不完全令人满意。

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

    object = [[Type alloc] init];
    

    总是明确安全的,即使 alloc 失败并返回 nil。所有这一切都会发生,对 init 的调用根本不会做任何事情,并且 object 将以值 nil 结束,因为将 init 发送到 nil 的结果也是 nil .

    话虽如此,Bill 和 Emmanuel 提供的答案应该是正确的。将您的结果直接与nil 或隐式与零进行比较。如果您稍后遇到崩溃,我猜这是因为您期望 myImageUrlmyImageNSString 以外的类型(我注意到您在原始版本中使用了无类型的 id代码)并向他们发送他们不回复的消息。

    【讨论】:

      【解决方案6】:
      NSDictionary *result;
      NSString *myImageURL = [result objectForKey:@"url"];
      if (myImageURL == NULL)
          myImageURL = @"";
      
      NSString *myImage = [result objectForKey:@"image"];
      if (myImageURL == NULL)
          myImage = @"";
      

      看看这是否有效,而不是过度考虑 NULL 类。

      【讨论】:

      • 不。我做了 NSLog 并得到了这个答案: result : { } 然后它就坏了。还不知道怎么了?
      • 你在 myImageURL 上做了一个 NSLog?在检查 null 之前?我可能会检查之前和之后。 NSLog(@"result: %@", [result objectForKey:@"url"]); NSLog(@"myImageURL: %@", myImageURL);
      【解决方案7】:

      这是另一个选项:

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

      【讨论】:

        【解决方案8】:

        这对我不起作用,我是这样想的

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

        【讨论】:

          【解决方案9】:

          好吧,这是@Iomec 几乎得到的实际答案

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

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

          您应该: 1) 测试 NSNull 空值 2) 如果不是 nil 则赋值

          如果您的代码还没有出故障,那么当您一天有 8 个应用在后台运行时,它就会投入生产。

          【讨论】:

            【解决方案10】:

            我在使用 JSONKit 时遇到了同样的问题。那里的实现是

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

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

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

            【讨论】:

              【解决方案11】:
                   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":"1cbrecbill@wricapitalgroup.com","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)
              
                                              }
              

              【讨论】:

                【解决方案12】:

                可能想通过检查以确保它不是字符串而不是仅仅检查它是否为 nil 来增加一点安全性。 (以确保它不是数字或您可能不想要的任何其他内容。)

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

                【讨论】:

                  【解决方案13】:

                  当您在可空字典中调用objectForKey时,应用程序崩溃了,所以我通过这种方式修复了这个问题以避免崩溃。

                  - (instancetype)initWithDictionary:(NSDictionary*)dictionary {
                  id object = dictionary;
                  
                  if (dictionary && (object != [NSNull null])) {
                      self.name = [dictionary objectForKey:@"name"];
                      self.age = [dictionary objectForKey:@"age"];
                  }
                  return self;
                  

                  }

                  【讨论】:

                    猜你喜欢
                    • 2013-07-18
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-06-05
                    • 1970-01-01
                    • 1970-01-01
                    • 2013-08-21
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多