10.5+/iOS的首选代码.
for (id object in array) {
// do something with object
}
此构造用于枚举符合NSFastEnumeration
协议的集合中的对象.这种方法具有速度优势,因为它将指向多个对象的指针(通过单个方法调用获得)存储在缓冲区中,并通过使用指针算法在缓冲区中前进来迭代它们.这比通过循环每次呼叫-objectAtIndex:
快much.
还值得注意的是,虽然从技术上讲,can使用for in循环来逐步完成NSEnumerator
,但我发现这实际上抵消了快速枚举的所有速度优势.原因是-countByEnumeratingWithState:objects:count:
的默认NSEnumerator
实现在每次调用时只在缓冲区中放置一个对象.
我在radar://6296108
篇文章中报道了这一点(NSE分子的快速枚举非常缓慢),但它被返回为未修复.原因是快速枚举预先获取一组对象,如果只想枚举到枚举器中的给定点(例如,直到找到特定对象或满足条件),并在中断循环后使用同一个枚举器,通常会跳过多个对象.
如果您是为OS X 10.6/iOS 4.0及以上版本编写代码,您还可以 Select 使用基于块的API枚举数组和其他集合:
[array enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
// do something with object
}];
还可以使用-enumerateObjectsWithOptions:usingBlock:
和pass NSEnumerationConcurrent
和/或NSEnumerationReverse
作为选项参数.
10.5之前的标准习惯用法是使用NSEnumerator
和while循环,如下所示:
NSEnumerator *e = [array objectEnumerator];
id object;
while (object = [e nextObject]) {
// do something with object
}
我建议保持简单.将自己绑定到一个数组类型是不灵活的,而且据称使用-objectAtIndex:
的速度增加对10.5+上的快速枚举的改进是微不足道的.(快速枚举实际上在底层数据 struct 上使用指针算法,并消除了大部分方法调用开销.)过早优化从来都不是一个好主意——它会导致更混乱的代码来解决一个不是瓶颈的问题.
使用100时,很容易切换到另一个可枚举集合(如NSSet
、NSDictionary
中的键等),甚至切换到103以向后枚举数组,所有这些都没有其他代码更改.如果迭代代码在一个方法中,您甚至可以传入任何NSEnumerator
,代码甚至不必关心它的迭代.此外,只要有更多对象,NSEnumerator
(至少是Apple code提供的)就会保留它正在枚举的集合,因此您不必担心自动释放的对象会存在多久.
也许NSEnumerator
(或快速枚举)能保护你的最大一件事是在你枚举without your knowledge时,在你的下面有一个可变集合(数组或其他)的改变.如果按索引访问对象,可能会遇到奇怪的异常或一个错误(通常是在问题发生很久之后)导致的错误,这对调试来说可能是可怕的.使用其中一种标准习惯用法的枚举具有"快速失败"行为,因此在发生Mutations 后try 访问下一个对象时,问题(由错误代码引起)将立即显现出来.随着程序变得更加复杂和多线程,甚至依赖于第三方代码可能修改的内容,脆弱的枚举代码变得越来越成问题.封装和抽象FTW!:-)