objective-c - 如何迭代 NSArray?

我正在寻找迭代 NSArray 的标准习语。我的代码需要适用于 OS X 10.4+。

最佳答案

10.5+/iOS 的普遍首选代码。

for (id object in array) {
    // do something with object
}

此构造用于枚举符合 NSFastEnumeration 的集合中的对象。协议(protocol)。这种方法具有速度优势,因为它将指向多个对象(通过单个方法调用获得)的指针存储在缓冲区中,并通过使用指针算法在缓冲区中前进来迭代它们。这比每次循环调用 -objectAtIndex:很多

还值得注意的是,虽然您在技术上可以使用 for-in 循环来单步执行 NSEnumerator,但我发现这几乎抵消了所有速度优势的快速枚举。原因是 -countByEnumeratingWithState:objects:count: 的默认 NSEnumerator 实现在每次调用时只在缓冲区中放置一个对象。

我在 radar://6296108 中报告了这一点(NSEnumerators 的快速枚举速度很慢),但它被返回为 Not To Be Fixed。原因是快速枚举会预取一组对象,如果您只想枚举到枚举器中的给定点(例如,直到找到特定对象或满足条件)并在中断后使用相同的枚举器在循环中,通常会跳过几个对象。

如果您正在为 OS X 10.6/iOS 4.0 及更高版本进行编码,您还可以选择使用基于 block 的 API 来枚举数组和其他集合:

[array enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
    // do something with object
}];

您也可以使用 -enumerateObjectsWithOptions:usingBlock: 并传递 NSEnumerationConcurrent 和/或 NSEnumerationReverse 作为选项参数。


10.4 或更早版本

10.5 之前的标准习惯用法是使用 NSEnumerator 和 while 循环,如下所示:

NSEnumerator *e = [array objectEnumerator];
id object;
while (object = [e nextObject]) {
  // do something with object
}

我建议保持简单。将自己绑定(bind)到数组类型是不灵活的,并且声称使用 -objectAtIndex: 的速度提高对于 10.5+ 上的快速枚举的改进是微不足道的。 (快速枚举实际上在底层数据结构上使用了指针算法,并消除了大部分方法调用开销。)过早的优化从来都不是一个好主意——它会导致更困惑的代码来解决一个无论如何都不是你的瓶颈的问题。

当使用 -objectEnumerator 时,您可以很容易地更改为另一个可枚举集合(如 NSSet,键入 NSDictionary 等),甚至切换到 -reverseObjectEnumerator 以向后枚举数组,所有这些都无需更改其他代码。如果迭代代码在一个方法中,您甚至可以传入任何 NSEnumerator 并且代码甚至不必关心它正在迭代的 什么。此外,只要有更多对象,NSEnumerator(至少由 Apple 代码提供的那些)就会保留它正在枚举的集合,因此您不必担心自动释放的对象将存在多长时间。

NSEnumerator(或快速枚举)保护您免受的最大影响可能是在您在您不知情的情况下重新列举它。如果您按索引访问对象,您可能会遇到奇怪的异常或一个错误(通常在问题发生很久之后),这对于调试来说可能是可怕的。使用标准惯用语之一进行枚举具有“快速失败”行为,因此当您在发生突变后尝试访问下一个对象时,问题(由不正确的代码引起)将立即显现出来。随着程序变得越来越复杂和多线程,甚至依赖于第三方代码可能修改的东西,脆弱的枚举代码变得越来越成问题。封装和抽象 FTW! :-)


https://stackoverflow.com/questions/992901/

相关文章:

objective-c - 类方法和实例方法有什么区别?

c - 是否可以使用 NSLog C 结构(如 CGRect 或 CGPoint)?

objective-c - 在objective-c/cocoa中抛出异常

objective-c - 比较浮点值有多危险?

ios - 在 iOS 中获取当前设备语言?

ios - 文件是通用的(三个切片),但它不包含 iOS 上静态库的(n)ARMv7-s 切片错误,

objective-c - "__block"关键字是什么意思?

ios - AVFoundation, captureStillImageAsynchronousl

ios - 如何隐藏 UINavigationBar 1px 底线

ios - @import 与 #import - iOS 7