在Objective-C中使用for each循环来访问NSMutable字典

284

我在Objective-C中访问可变字典的键和值时遇到了一些困难。

假设我有以下字典:

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

我可以设置键和值。现在,我只想访问每个键和值,但我不知道设置了多少个键。

在 PHP 中,这非常简单,可以使用以下代码:

foreach ($xyz as $key => $value)

在 Objective-C 中如何实现?

7个回答

689
for (NSString* key in xyz) {
    id value = xyz[key];
    // do stuff
}

这适用于符合NSFastEnumeration协议(在10.5+和iOS上可用)的每个类,不过NSDictionary是为数不多的几个集合之一,可以枚举键而不是值。我建议您阅读关于快速枚举的内容,该内容位于集合编程主题中。

哦,我应该补充说明,您在枚举集合时绝不能修改它。


4
我在想,这应该不是:for (NSString* key in [xyz allKeys])吗?或者说这并不重要。 - Just a coder
8
枚举字典实际上是枚举其键。“for (NSString* key in [xyz allKeys])”在概念上是相同的。 - zneak
如果您需要在枚举键时改变字典,请使用[xyz allKeys]。请参见下面的答案。 - Brody Robertson
这个循环每次返回的顺序都一样吗?还是我们需要另一种方法来在TableView的section中使用它? - ymutlu
1
@ymutlu,Cocoa字典是无序的。这意味着当您修改它们时,它们迭代的顺序可能会发生变化。 - zneak
但是这难道不会导致每个键都需要使用下标运算符进行另一个O(log n)的查找吗?当迭代字典时,理想情况下不需要这样做,或者背后有一些神奇的东西可以真正使其快速吗? - Felix Dombek

102

为了不遗漏使用块枚举键和值的10.6+选项...

[dict enumerateKeysAndObjectsUsingBlock:^(id key, id object, BOOL *stop) {
    NSLog(@"%@ = %@", key, object);
}];

如果您想让操作并发执行:

[dict enumerateKeysAndObjectsWithOptions:NSEnumerationConcurrent
                              usingBlock:^(id key, id object, BOOL *stop) {
    NSLog(@"%@ = %@", key, object);
}];

3
枚举字典的3种不同方法...嘿,这让我想起了“最奇怪的语言特性”答案,VB有7种不同类型的循环。 - dreamlax
3
好的,objectEnumerator是在1994年添加的,for(...in...)大约在2006年添加,而Blocks则是在2009年添加的。块形式的枚举是自然产生的结果。 - bbum
这似乎比标准的for...in结构更快:http://oneofthesedaysblog.com/block-vs-for-in-objective-c-enumeration - lkraider
1
@lkraider,我在那篇帖子中发表了评论,实际上是在比较块枚举与旧版for循环而不是for...in结构。 - Quinn Taylor
另外,由于Objective C的特性以及其缺少方法重载的能力,您可以为键和对象指定类型。例如:... enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, UIImage *img, BOOL *stop) { ... - mkko
显示剩余2条评论

16

如果您需要在枚举时改变字典:

for (NSString* key in xyz.allKeys) {
    [xyz setValue:[NSNumber numberWithBool:YES] forKey:key];
}

1
原因是allKeys返回键的副本。因此,对字典进行变异是安全的。 - Honghao Z

5

枚举字典最简单的方法是

for (NSString *key in tDictionary.keyEnumerator) 
{
    //do something here;
}

其中tDictionary是您想要迭代的NSDictionaryNSMutableDictionary


5

这些是不错的链接,尽管@zneak发布的代码如果你可以构建10.5+或iPhone,则更简单和更快。 - Quinn Taylor

3

快速枚举是在10.5和iPhone操作系统中添加的,它比旧方法更快,不仅仅是语法糖。如果你需要针对老版本运行时(即10.4及以前版本),你必须使用旧的枚举方法:

NSDictionary *myDict = ... some keys and values ...
NSEnumerator *keyEnum = [myDict keyEnumerator];
id key;

while ((key = [keyEnum nextObject]))
{
    id value = [myDict objectForKey:key];
    ... do work with "value" ...
}

您没有释放枚举器对象,也无法重置它。如果您想重新开始,请从字典中请求一个新的枚举器对象。


2

2
没错,但这会创建一个额外的自动释放数组,对于具有许多键的字典来说可能非常浪费。 - Quinn Taylor

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