Objective-C中的“for each”(快速枚举)-- 集合的评估?

11

从实验来看,集合表达式只被评估一次。考虑下面的例子:

static NSArray *a;

- (NSArray *)fcn
{
    if (a == nil)
        a = [NSArray arrayWithObjects:@"one", @"two", @"three", nil];
    NSLog(@"called");
    return a;
}

...

for (NSString *s in [self fcn])
    NSLog(@"%@", s);
输出结果为:
2010-10-07 07:37:31.419 WidePhotoViewer Lite[23694:207] called
2010-10-07 07:37:31.420 WidePhotoViewer Lite[23694:207] one
2010-10-07 07:37:31.425 WidePhotoViewer Lite[23694:207] two
2010-10-07 07:37:31.425 WidePhotoViewer Lite[23694:207] three

请问有人能确认这是指仅会调用一次[self fcn]的规定行为吗?

我的想法是做类似于这样的事情:

for (UIView *v in [innerView subviews]) {

不要这样做:

NSArray *vs = [innerView subviews];
for (UIView *v in vs) {

有什么想法?


感谢那些尝试回答的人,特别是Shmurk,这确实让问题变得清晰了。检查实现以阐明规范是危险的。无论如何,我在准备问题时已经做过了。 - Marc Rochkind
4个回答

13

这种 for 循环被称为“快速枚举”(请查看 NSFastEnumeration 对象)。苹果的文档称,在“for obj in expression”中,expression 产生一个符合 NSFastEnumeration 协议的对象,所以我猜这就是正确的行为:该函数被调用一次,迭代器被创建一次并在循环中使用。


7
实际上,collection 只被评估一次,在 clang 的源代码中可以查看。当文档不够明确时,您需要相信实现。
是的,我认为苹果应该澄清文档。请提交一个 bug,Marc!
获得此信息的一种严谨方法是阅读官方文档的边距,可以在这里找到。它指出:

枚举器具有变异保护,因此如果您在枚举期间尝试修改集合,则会引发异常。由于禁止在迭代过程中修改对象,因此可以同时执行多个枚举。

因此,您迭代的集合无论如何都不能更改。它没有说明是否在

评估了 collection
for(id obj in collection) { ... } 

一或两次之后,生成的对象就不能再改变了。


3

0

这是快速枚举行为的一部分。如果想要深入了解快速枚举的实现,请查看NSBlog上的这篇博客文章:实现快速枚举。


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