如何检查一个NSDictionary或NSMutableDictionary是否包含某个键?

467

我需要检查一个字典中是否存在某个键。如何实现?


4
(仅供任何通过谷歌搜索到此处的人参考。请注意,这是一个非常旧的问题。下面SaintMacintosh的答案是最先进的技术,比这个QA提前了五年。希望能有所帮助。) - Fattie
1
实际上,Andy Dent的回答也提供了最新的状态和更多的上下文信息。而且比SaintMacintosh更早地完成了这一点。做个好事,向下滚动一点。 - Peter Kämpf
1
他使用:keysByName[test] != nil,!= nil 检查是多余的,并且在我看来不够可读。我只想为那些寻找语法的人分享一个 TL;DR 版本。 - Andrew Hoos
我同意@SaintMacintosh的观点。他的回答更加简洁明了。 - SAS
如果您想检查 NSDictionary 是否包含任何键(非特定),则应使用 [dictionary allKeys].count == 0。 如果 count0,则 NSDictionary 中没有键。 - Aleksander Azizi
16个回答

780

objectForKey如果对应的 key 不存在,会返回 nil。


29
如果这个键存在,但是它对应的值为nil,那该怎么办? - Fyodor Soikin
234
不可能的。你不能将nil添加到NSDictionary中。你需要使用[NSNull null]代替。 - Ole Begemann
10
如果您尝试插入空值,NS字典将引发NSInvalidArgumentException异常,因此不应存在键存在但相应值为nil的情况。 - Brad The App Guy
3
你为什么不想使用valueForKey呢?这会在必要时调用objectForKey。 - khatchad
7
绝对不要使用 valueForKey 来处理 JSON 字典。这是因为 JSON 可以包含任意字符串作为键名。比如,如果它包含 "@count" 作为键名,那么 objectForKey:@"@count" 将会给出正确的值,但是 valueForKey:@"@count" 将会返回键/值对的数量。 - gnasher729
显示剩余4条评论

164
if ([[dictionary allKeys] containsObject:key]) {
    // contains key
    /* Don't use this solution. Look for more details in comments. */
}

或者

if ([dictionary objectForKey:key]) {
    // contains object
}

104
这个答案中的例子很慢。 - James Van Boxtel
8
请注意,此答案中的示例一应被视为非法(O(n)而不是O(1))。 - Hertzel Guinness
5
表现非常重要。确实,这句话可能不相关,但如果它被重复了n次,那么它就需要花费n*m的时间,你可能不知道为什么程序变慢了。几乎所有东西在一开始或小规模情况下都很快。但随着程序的增长,使用错误的数据结构(例如在第一个例子中使用数组而不是字典)会导致你付出高昂的代价。 - Andrew Hoos
2
检查字典(或集合)中是否存在键的时间复杂度期望为O(1),最坏情况下为O(n),而不是O(log(n))。苹果的文档清楚地解释了这一点。 - Andrew Hoos
@JoeBlow “动画化3D Mecanim点”听起来你把Cocoa Touch/Objective-C和Unity Engine/C#混淆了。的确,Unity引擎在其运行平台上效率非常低下。然而,Objective-C/Swift应用程序并不是本质上低效的,也不是大多数经验丰富的iOS开发人员没有积极意识到他们代码的效率。至于“只与(4个活着的)性能程序员有关”——显然你不是游戏开发者。在不耗电的情况下以60FPS呈现出优秀的图形和游戏玩法是一个持续的挑战。 - Slipp D. Thompson
[dictionary allKeys] 返回的是类似于 Set 的数据结构还是类似于 Array 的数据结构?Set 应该是 O(1) 查询,而 Array 应该是 O(n) 查询。 - wz366

101

Objective-C和Clang的较新版本使用现代语法:

if (myDictionary[myKey]) {

}

不必检查是否为nil相等,因为字典(或数组)中只能存储非nil的Objective-C对象。而所有Objective-C对象都是真实值。即使是@NO, @0[NSNull null]也会被视为true。

编辑:Swift现在也可以使用了。

对于Swift,您可以尝试以下内容:

if let value = myDictionary[myKey] {

}

如果myKey在字典中,则执行if语句块,并将其值存储在value变量中。请注意,即使是falsey值(如0),此语法也适用。


谢谢!我只是好奇,但我在Objective-C类参考文档中找不到这种行为的记录。https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/Reference/Reference.html#//apple_ref/occ/instm/NSDictionary/ 我是不是眼瞎了? - irh
2
不,你不是眼瞎。它只是没有强调。但是可以在这里看到(使用clang)和这里(现代的objc: 非常底部)以及在这里(集合指南:搜索字典)。 - Andrew Hoos

22
if ([mydict objectForKey:@"mykey"]) {
    // key exists.
}
else
{
    // ...
}

9
使用JSON字典时:
#define isNull(value) value == nil || [value isKindOfClass:[NSNull class]]

if( isNull( dict[@"my_key"] ) )
{
    // do stuff
}

8

我喜欢Fernandes的答案,尽管您两次请求obj。

这也可以做到(与Martin的A差不多)。

id obj;

if ((obj=[dict objectForKey:@"blah"])) {
   // use obj
} else {
   // Do something else like creating the obj and add the kv pair to the dict
}

马丁和这个答案都适用于iPad2 iOS 5.0.1 9A405。

5
是的。这种错误非常常见,会导致应用程序崩溃。因此,在每个项目中,我都会添加以下代码作为NSDictionary:
// .h文件代码:
@interface NSDictionary (AppDictionary)

- (id)objectForKeyNotNull : (id)key;

@end

//.m文件的代码如下

#import "NSDictionary+WKDictionary.h"

@implementation NSDictionary (WKDictionary)

 - (id)objectForKeyNotNull:(id)key {

    id object = [self objectForKey:key];
    if (object == [NSNull null])
     return nil;

    return object;
 }

@end

你可以像下面这样在代码中使用:

NSStrting *testString = [dict objectForKeyNotNull:@"blah"];

5

有一个非常讨厌的问题浪费了我一些时间来调试 - 您可能会发现自动完成提示您尝试使用doesContain,它似乎可以工作。

但是,doesContain使用id比较而不是objectForKey使用的哈希比较,因此如果您有一个字符串键的字典,它将返回NO到doesContain

NSMutableDictionary* keysByName = [[NSMutableDictionary alloc] init];
keysByName[@"fred"] = @1;
NSString* test = @"fred";

if ([keysByName objectForKey:test] != nil)
    NSLog(@"\nit works for key lookups");  // OK
else
    NSLog(@"\nsod it");

if (keysByName[test] != nil)
    NSLog(@"\nit works for key lookups using indexed syntax");  // OK
else
    NSLog(@"\nsod it");

if ([keysByName doesContain:@"fred"])
    NSLog(@"\n doesContain works literally");
else
    NSLog(@"\nsod it");  // this one fails because of id comparison used by doesContain

5

使用Swift,代码如下:

if myDic[KEY] != nil {
    // key exists
}

3

用于检查NSDictionary中键是否存在的方法:

if([dictionary objectForKey:@"Replace your key here"] != nil)
    NSLog(@"Key Exists");
else
    NSLog(@"Key not Exists");

2
这实际上只是这个现有答案的重复。 - Pang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接