Проверьте, существует ли ключ в NSDictionary, является нулем или нет - PullRequest
14 голосов
/ 11 августа 2011

Я искал, как проверить, существует ключ 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'

Ответы [ 13 ]

14 голосов
/ 03 октября 2014

Томми объяснил это прекрасно.

Я рекомендую создать расширение класса 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"];

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

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

14 голосов
/ 12 августа 2011

Правильный ответ:

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

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

Спасибо за все объяснения.

7 голосов
/ 16 июля 2013

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

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

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

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

[dictionary allKeys]
6 голосов
/ 11 августа 2011

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

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

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

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

Это то, что я бы сделал в вашем коде.

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

4 голосов
/ 12 августа 2011

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

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

object = [[Type alloc] init];

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

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

2 голосов
/ 24 января 2013

это еще один вариант:

if (![result objectForKey:@"image"])
    {
        NSLog(@"doesn't exist");
    }
    if ([result objectForKey:@"image"])
    {
        NSLog(@"exist");
    }
2 голосов
/ 11 августа 2011
NSDictionary *result;
NSString *myImageURL = [result objectForKey:@"url"];
if (myImageURL == NULL)
    myImageURL = @"";

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

Посмотрите, работает ли это, а не продумывайте класс NULL.

1 голос
/ 13 марта 2013

Хорошо, вот фактический ответ, который @Iomec почти получил

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

Это действительно правильный ответ, потому что он равен нулю, и когда вы говорите myImage = [receiveObject ...]; затем, если myImage = nil, вы фактически приводите нулевое значение (nil) в класс, который является исключением, если не запущенной ошибкой.

Вы должны: 1) проверка на нулевое значение NSNull 2) если не ноль, тогда присваивают

Если ваш код еще не вышел из строя, он будет запущен, когда у вас в фоновом режиме будет запущено 8 приложений.

1 голос
/ 02 марта 2013

это не сработало для меня, я понял это так

id myImageURL = [result objectForKey:@"url"];
if ([myImageURL isKindOfClass:[NSNull class]])  
    myImageURL = @"";
0 голосов
/ 10 августа 2018

Когда вы вызываете 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;

}

...