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

Mar*_*ind 11 iphone foreach objective-c 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);
Run Code Online (Sandbox Code Playgroud)

输出是:

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
Run Code Online (Sandbox Code Playgroud)

表示[self fcn]只被调用一次.

任何人都可以确认这是指定的(而不仅仅是观察到的)行为吗?

我的想法是做这样的事情:

for (UIView *v in [innerView subviews]) {
Run Code Online (Sandbox Code Playgroud)

而不是这个:

NSArray *vs = [innerView subviews];
for (UIView *v in vs) {
Run Code Online (Sandbox Code Playgroud)

思考?

小智 13

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


Yuj*_*uji 7

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

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

获得这个的一种迂腐方式是阅读官方文档的边距,可以在这里找到.它说明了

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

所以,你迭代的集合无论如何都无法改变.它没有透露是否计算collection

for(id obj in collection) { ... } 
Run Code Online (Sandbox Code Playgroud)

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