NSDictionary 如何处理 NIL 对象?

发布于 2024-11-25 23:28:27 字数 614 浏览 0 评论 0原文

考虑下面的代码。本质上,我们得到 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
                       ];

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

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

星星的軌跡 2024-12-02 23:28:27

nil 用作标记“参数结束”列表的“哨兵”。如果 twitterToken 为 nil,运行时将遍历您的参数,一旦到达 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 with Love 的文章:http://cocoawithlove.com/2009/05/variable-argument-lists-in-cocoa.html

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

悲念泪 2024-12-02 23:28:27

而不是使用 initWithObjectAndKeys 进行初始化。为什么不实例化一个 NSMutableDictionary 然后添加键值对(如果键为 null 则不添加)?

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

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

// ... etc

如果您想从那时起保持它不可变,您可以稍后将其转换回 NSDictionary。

更新

只是回应Josh的评论,我应该澄清一下,当然cast 不会神奇地将参数 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; }

这将生成以下编译器警告(对我来说,警告会生成错误,编译错误):

file:blah.m: 错误:语义问题:“NSDictionary”可能无法响应“setObject:forKey:”

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:'

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文