目标c“为每个”(快速枚举) - 收集评估?

时间:2010-10-07 13:45:59

标签: iphone objective-c foreach fast-enumeration

从实验看,集合表达式只被评估一次。考虑这个例子:

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) {

思想?

4 个答案:

答案 0 :(得分:13)

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

答案 1 :(得分:7)

在实践中,collection仅被评估一次,例如,您可以检查铿锵的来源。当文档没有说明足够精确的内容时,您需要相信实现。

是的,我认为Apple应该澄清文档。请提交一个错误,Marc!

获得此功能的一种迂腐方式是阅读官方文档的边距,可以找到here。据说

  

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

所以,你迭代的集合无论如何都无法改变。它没有说明它是否在

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

一次或两次,生成的对象无法更改。

答案 2 :(得分:3)

常识决定它是那样的。但由于快速枚举文档中没有直接说明,为什么不看一下协议本身:

http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/NSFastEnumeration_protocol/Reference/NSFastEnumeration.html

此协议不提供像nextObject或objectAtIndex之类的方法,而是提供类似的方法,而是请求C对象数组,然后对其进行迭代。

虽然有强烈的迹象,但没有文件保证表达式只被评估一次。

答案 3 :(得分:0)

这是快速枚举行为的一部分。有关快速枚举实现的一些深入知识,请查看NSBlog上的这篇博文:Implementing Fast Enumeration.