【问题标题】:Objective c "for each" (fast enumeration) -- evaluation of collection?Objective c“for each”(快速枚举)——评估集合?
【发布时间】:2011-04-22 09:18:23
【问题描述】:

从实验看来,集合表达式只计算一次。考虑这个例子:

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

想法?

【问题讨论】:

  • 感谢那些,特别是。试图回答的史穆克……这确实对此事有所启发。 (检查实现以澄清规范是危险的。无论如何,我在准备问题时已经这样做了。)

标签: iphone objective-c foreach fast-enumeration


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    在实践中,collection 只被评估一次,你可以查看 clang 的来源,例如。当文档说的不够准确时,您需要信任实现。

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

    一个迂腐的方法是阅读官方文档的边缘,可以找到here。据说

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

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

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

    一次或两次,生成的对象不能改变。

    【讨论】:

      【解决方案3】:

      常识要求它是这样的。但是既然Fast Enumeration Documentation中没有直接说明,为什么不看一下协议本身:

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

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

      尽管有强烈的迹象,但没有任何文档可以保证表达式只计算一次。

      【讨论】:

        【解决方案4】:

        这是快速枚举行为的一部分。如需深入了解快速枚举的实现,请查看 NSBlog 上的这篇博文:Implementing Fast Enumeration.

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-03-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-03
          • 1970-01-01
          • 1970-01-01
          • 2020-05-19
          相关资源
          最近更新 更多