开发者

How does NSDictionary handle NIL objects?

Consider the code below. In essence, we get 2 strings, then we add these values to the NSDictionary.

However, i hit a weird bug. When fbAccessTokenKey is 0x0 (or nil), then twitterToken would not be added as well.

NSString *fbAccessTokenKey=[[UserStockInfo sharedUserStockInfo] getFBAccessTokenKey];
NSString *twitterToken=[[UserStockInfo sharedUserStockInfo] getTwitterAccessTo开发者_如何学JAVAkenKey];

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

Why is this happening, and what is a good way of resolving this?


nil is used as a 'sentinel' for marking the "end of arguments" list. If twitterToken was nil, the runtime would go through your arguments, and once it got to twitterToken, it would think that it was up to the end of your list of objects and keys. This is due to the way that C/Obj-C is implemented when it comes to list arguments.

The alternative safe way to do it is to use an NSMutableDictionary, and check to see if your values are non-nil, then add them to the mutable dictionary like this:

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

For more technical info, there's a good article on Cocoa with Love: http://cocoawithlove.com/2009/05/variable-argument-lists-in-cocoa.html


You can use the NSNull object. Documentation here: http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSNull_Class/Reference/Reference.html


Rather than initializing with initWithObjectAndKeys. Why not instantiate an NSMutableDictionary and then add the key value pairs (or not if the key is null)?

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

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

// ... etc

You could cast it back to an NSDictionary later if you want to keep it immutable from that point.

Update

Just a note in response to Josh's comment, I should clarify that of course the cast will not magically convert the params NSMutableDictionary to an NSDictionary. But if you are passing it to code which requires an NSDictionary, the cast will let you treat it as such.

Josh's comment includes this code:

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; }

This will generate the following compiler warning (and for me, with warnings generating errors, a compile error):

file:blah.m: error: Semantic Issue: 'NSDictionary' may not respond to 'setObject:forKey:'

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜