Как NSDictionary обрабатывает объекты NIL? - PullRequest
5 голосов
/ 26 июля 2011

Рассмотрим код ниже. По сути, мы получаем 2 строки, затем добавляем эти значения в NSDictionary.

Однако я наткнулся на странную ошибку. Если fbAccessTokenKey равен 0x0 (или nil), то twitterToken также не будет добавлен.

NSString *fbAccessTokenKey=[[UserStockInfo sharedUserStockInfo] getFBAccessTokenKey];
NSString *twitterToken=[[UserStockInfo sharedUserStockInfo] getTwitterAccessTokenKey];

NSDictionary *params= [[NSDictionary alloc] initWithObjectsAndKeys:
                       fbAccessTokenKey, @"fb_access_token", 
                       twitterToken, @"twitter_access_token", 
                       nil
                       ];

Почему это происходит, и как это можно решить?

Ответы [ 3 ]

14 голосов
/ 26 июля 2011

nil используется в качестве «стража» для маркировки списка «конец аргументов». Если бы twitterToken было равно нулю, среда выполнения проверила бы ваши аргументы, и как только он достигнет twitterToken, она бы подумала, что до конца списка объектов и ключей нет. Это связано с тем, что C / Obj-C реализован, когда дело доходит до аргументов списка.

Альтернативный безопасный способ сделать это - использовать NSMutableDictionary и проверить, не являются ли ваши значения ненулевыми, а затем добавить их в изменяемый словарь, например:

NSString *fbAccessTokenKey = [[UserStockInfo sharedUserStockInfo] getFBAccessTokenKey];
NSString *twitterToken = [[UserStockInfo sharedUserStockInfo] getTwitterAccessTokenKey];

NSMutableDictionary *params = [NSMutableDictionary dictionary];
if (fbAccessTokenKey) [params setObject:fbAccessTokenKey forKey:@"fb_access_token"];
if (twitterToken) [params setObject:twitterToken forKey:@"twitter_access_token"];

Для получения дополнительной технической информации, есть хорошая статья о Какао с Любовью: http://cocoawithlove.com/2009/05/variable-argument-lists-in-cocoa.html

4 голосов
/ 26 июля 2011

Вы можете использовать объект NSNull.Документация здесь: http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSNull_Class/Reference/Reference.html

2 голосов
/ 26 июля 2011

Вместо инициализации с помощью initWithObjectAndKeys. Почему бы не создать экземпляр NSMutableDictionary, а затем добавить пары ключ-значение (или нет, если ключ имеет значение null)?

NSMutableDictionary * params = [[NSMutableDictionary alloc] init];

if (fbAccessTokenKey)
    [params setObject:fbAccessTokenKey forKey:@"fb_access_token];

// ... etc

Вы можете привести его обратно к NSDictionary позже, если вы хотите сохранить его неизменным с этого момента.

Обновление

Просто примечание в ответ на комментарий Джоша , я должен уточнить, что, конечно, приведение не будет магически преобразовывать параметры NSMutableDictionary в NSDictionary. Но если вы передаете его в код, который требует NSDictionary, приведение позволит вам обращаться с ним как таковым.

Комментарий Джоша включает в себя этот код:

NSMutableDictionary * md = [[NSMutableDictionary alloc] init]; 
NSDictionary * d = (NSDictionary *)md; 
[d setObject:@"Yes I am" forKey:@"Still mutable?"]; 
NSLog(@"%@", d); // Prints { "Still mutable?" = Yes I am; }

Это сгенерирует следующее предупреждение компилятора (и для меня, с предупреждениями, генерирующими ошибки, ошибку компиляции):

файл: blah.m: ошибка: семантическая проблема: «NSDictionary» может не отвечать на «setObject: forKey:»

...