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