从实验看,集合表达式只被评估一次。考虑这个例子:
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) {
思想?
答案 0 :(得分:13)
这种for循环称为“快速枚举”(查看NSFastEnumeration对象)。 Apple的文档说,在“for obj in expression”中,表达式产生一个符合NSFastEnumeration协议的对象,所以我猜这是正确的行为:函数被调用一次,迭代器被创建一次并在循环中使用。
答案 1 :(得分:7)
在实践中,collection
仅被评估一次,例如,您可以检查铿锵的来源。当文档没有说明足够精确的内容时,您需要相信实现。
是的,我认为Apple应该澄清文档。请提交一个错误,Marc!
获得此功能的一种迂腐方式是阅读官方文档的边距,可以找到here。据说
枚举器具有变异防护,因此如果您在枚举期间尝试修改集合,则会引发异常。由于禁止在迭代期间突变对象,因此可以同时执行多个枚举。
所以,你迭代的集合无论如何都无法改变。它没有说明它是否在
中评估collection
for(id obj in collection) { ... }
一次或两次,生成的对象无法更改。
答案 2 :(得分:3)
常识决定它是那样的。但由于快速枚举文档中没有直接说明,为什么不看一下协议本身:
此协议不提供像nextObject或objectAtIndex之类的方法,而是提供类似的方法,而是请求C对象数组,然后对其进行迭代。
虽然有强烈的迹象,但没有文件保证表达式只被评估一次。
答案 3 :(得分:0)
这是快速枚举行为的一部分。有关快速枚举实现的一些深入知识,请查看NSBlog上的这篇博文:Implementing Fast Enumeration.