NSDictionary如何处理NIL对象?

考虑下面的代码。 本质上,我们得到2个string,然后我们将这些值添加到NSDictionary。

但是,我打了一个奇怪的错误。 当fbAccessTokenKey是0x0(或零),那么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 ]; 

为什么会发生这种情况,解决这个问题的好方法是什么?

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"]; 

欲了解更多技术信息,有一个关于cocoa与爱情的好文章: http : //cocoawithlove.com/2009/05/variable-argument-lists-in-cocoa.html

你可以使用NSNull对象。 文档在这里: http : //developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSNull_Class/Reference/Reference.html

而不是用initWithObjectAndKeys初始化。 为什么不实例化一个NSMutableDictionary,然后添加键值对(或者如果键是空的话)?

 NSMutableDictionary * params = [[NSMutableDictionary alloc] init]; if (fbAccessTokenKey) [params setObject:fbAccessTokenKey forKey:@"fb_access_token]; // ... etc 

如果你想从这一点保持不变的话,你可以把它转换回NSDictionary。

更新

只是为了回应Josh的评论,我应该澄清,当然,演员不会神奇转换参数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:'