【问题标题】:Strange for loops I'm not familiar with: "for (id * in *)"我不熟悉的奇怪 for 循环:“for (id * in *)”
【发布时间】:2013-05-23 22:45:39
【问题描述】:

如果这个问题过于简单,我深表歉意,但我已经疯狂地用 Google 搜索,找不到合适的解释。

for (id line in self.lines){
    [linesCopy addObject:[line copyWithZone:zone]];
}

我只是在学习 Objective-C,这是我以前从未见过的for 循环的一种形式。我熟悉简单的

for (int x = 1, x < 10, x++)

for 循环的样式。

【问题讨论】:

  • 谷歌“快速枚举”
  • 哇,这个正确答案的竞争异常激烈!
  • 这就是为什么每个人都应该阅读教程。

标签: objective-c for-loop fast-enumeration


【解决方案1】:

来自Cocoa Core Competencies: Enumeration:

快速枚举

几个 Cocoa 类,包括集合类,采用NSFastEnumeration 协议。您可以使用它使用类似于标准 C for 循环的语法来检索实例保存的元素,如下例所示:

NSArray *anArray = // get an array;
for (id element in anArray) {
    /* code that acts on the element */
}

顾名思义,快速枚举比其他形式的枚举更有效。

如果您不知道,id 是一种 Objective-C 类型,基本上意味着“指向任何 Objective-C 对象的指针”。请注意,id 的指针是内置的;你通常不想说id *。

如果您希望 anArray 的元素属于特定类,例如 MyObject,您可以改用它:

for (MyObject *element in anArray) {
    /* code that acts on the element */
}

但是,编译器和运行时都不会检查元素是否确实是MyObject 的实例。如果anArray 的元素不是MyObject 的实例,您可能最终会尝试向它发送一条它不理解的消息,并得到一个选择器无法识别的异常.

【讨论】:

    【解决方案2】:

    这是这种常见形式的简写形式:

    for (int i = 0; i < [self.lines count]; i++) {
        id line = [self.lines objectAtIndex:i];
        // ...
    }
    

    这是一种常见的循环习惯用法(一次遍历某个集合、数组、集合等),以至于它已被转换为这样的简写形式,称为“快速枚举”。

    事实上,在它的内部实现中,它实际上比自己做的要快一些,所以无论是清晰度还是性能都更可取。

    【讨论】:

    • 它既不使用count也不使用objectAtIndex:消息。
    • @robmayoff 显然不是;我没有声称它确实如此。但这是它取代的常见形式,并且 OP 是 ObjC 语法的新内容。
    • 也许“等价”在这里是一个强词 - 一方面,你可以快速枚举一个集合,它甚至没有实现objectAtIndex:,所以在我的书中它们不是“等价的”。但同意,我们正在讨论细节。
    【解决方案3】:

    这是一个可以与符合NSFastEnumeration 协议的类一起使用的语句。当你有这个可用时,Objective-C 编程指南建议你使用它。看看here。这是一种无需传统 for (int i = 0; i &lt; length; ++i) 语法即可遍历集合的方法。

    请注意,它通常不支持在以这种方式迭代时删除和插入元素(也可以使用普通的for 循环,无论如何您都应该注意索引)。

    基本上所有标准集合都支持这种迭代方式。

    【讨论】:

      【解决方案4】:

      称为forin 循环,也称为快速枚举。基本上,语法是:

      for (SomeObjectIAmExpecting *localVariableName in anArrayOfObjects)
      {
          if (![localVariableName isKindOfClass:[SomeObjectIAmExpecting class]]) continue; //To avoid errors.
           //do something to them
      }
      

      【讨论】:

      • 怎么样:for (Class *object in collection)
      • 谢谢!这是其中包含不可能精确搜索的关键字的事物之一。预期对象是否必须(或可转换为)与数组中的对象类型相同?
      • @RobertHall 不,但请记住,无论它是什么。如果您期待一个NSString 而您得到一个NSNumber,那么您显然无法获得它的length。因此,您有时必须检查课程。见编辑。
      • @Undo 为什么使用if (!(foo == bar)) 而不是if (foo != bar)?结果相同,但与您正在做的事情不同。
      • @rmaddy 因为我的做法很奇怪——现在是“正常人”的做法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-05
      • 2019-02-11
      • 2019-04-30
      • 2017-04-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多