Подтвердить что ты не робот

Проверить, существует ли ключ в 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 = @"";

Проверить, что 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'
4b9b3361

Ответ 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"];

Таким образом, как объяснил Томми, вы отправляете вызов метода на нуль, который не приведет к сбою приложения, но ваш объект получит нулевое значение.

Надеюсь, что это поможет.

Ответ 3

ответ ниже работал у меня:

fooobar.com/questions/15994/...

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

Также обратите внимание, что вы можете получить массив ключей в словаре, используя

[dictionary allKeys]

Ответ 4

Всякий раз, когда я пытаюсь проверить, является ли объект, возвращаемый из словаря, нулевым, я делаю это:

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

Тогда в вашем коде это будет:

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

Что бы я сделал в вашем коде.

Кроме того, просто убедитесь, что результат NSDictionary определен? В вашем коде у него нет ничего, на что он установлен. Он просто определяется как переменная, которую вы планируете использовать вызванные результаты

Ответ 5

Если объект не существует для ключа, NSDictionary вернет nil. NSNull - это фактический объект, а значит, и отдельная вещь. Это похоже на различие между возможностью записи того, что значение и значение равны нулю, и не записывать, было ли значение. Это также немного зависит от того, как вы думаете в терминах C указаний на указатель на объект, а не только на объект, поэтому он не полностью семантически приятен с этой точки зрения.

В Objective-C вы можете отправить любое сообщение nil, и гарантированно будет nil (или 0). Поэтому, если ваш код предназначен для обеспечения того, что у вас есть ссылка на безопасный объект, как вы могли бы на С++, то то, что вы делаете, не нужно. Составные утверждения вроде:

object = [[Type alloc] init];

Всегда явно безопасны, даже если alloc не работает и возвращает nil. Все, что произойдет, это то, что вызов init вообще ничего не сделает, и объект будет иметь значение nil, потому что результат отправки init в nil также nil.

Таким образом, ответы, представленные Биллом и Эммануилом, должны быть правильными. Сравните результат напрямую с nil или неявно с нулем. Если позже вы получите сбой, я угадаю, потому что вы ожидаете, что myImageUrl и myImage будут типами, отличными от NSString (я замечаю, что вы использовали безличный id в своем оригинале код) и отправляет им сообщение, на которое они не отвечают.

Ответ 6

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

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

Посмотрите, работает ли это, а не переоценивает класс NULL.

Ответ 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":"[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)

                                }

Ответ 12

Возможно, вы захотите добавить немного больше безопасности, проверив, чтобы убедиться, что это НЕ строка, а не просто проверка, является ли она нулем. (Чтобы убедиться, что это не номер или что-то еще, что вам может не понадобиться.)

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