3 回答
TA贡献1712条经验 获得超3个赞
10.5 + / iOS的一般首选代码。
for (id object in array) {
// do something with object
}
此构造用于枚举符合NSFastEnumeration协议的集合中的对象。这种方法具有速度优势,因为它将指向多个对象的指针(通过单个方法调用获得)存储在缓冲区中,并使用指针算法通过在缓冲区中前进来遍历它们。这是很多比调用速度-objectAtIndex:通过每一次循环中。
还值得注意的是,虽然从技术上讲您可以使用for-in循环逐步执行NSEnumerator,但我发现这实际上使快速枚举的所有速度优势无效。原因是默认NSEnumerator实现-countByEnumeratingWithState:objects:count:只在每次调用时在缓冲区中放置一个对象。
我在radar://6296108(NSEnumerators的快速枚举速度缓慢)中报告了此问题,但返回结果为“不固定”。原因是快速枚举会预取一组对象,并且如果您只想枚举枚举器中的给定点(例如,直到找到特定的对象或满足条件),并在中断后使用相同的枚举器在循环中,通常会跳过多个对象。
如果要为OS X 10.6 / iOS 4.0及更高版本进行编码,则还可以选择使用基于块的API枚举数组和其他集合:
[array enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
// do something with object
}];
您还可以使用-enumerateObjectsWithOptions:usingBlock:和传递NSEnumerationConcurrent和/或NSEnumerationReverse作为options参数。
10.4或更早版本
10.5之前版本的标准习惯用法是使用NSEnumeratorwhile循环,如下所示:
NSEnumerator *e = [array objectEnumerator];
id object;
while (object = [e nextObject]) {
// do something with object
}
我建议保持简单。将自己绑定到数组类型是不灵活的,-objectAtIndex:无论如何,所谓的使用速度增加与在10.5+上进行快速枚举所带来的改善无关紧要。(快速枚举实际上是在基础数据结构上使用指针算术,并消除了大多数方法调用开销。)过早的优化从来都不是一个好主意-它导致混乱的代码来解决不是您的瓶颈的问题。
使用时-objectEnumerator,您很容易更改为另一个可枚举的集合(如NSSet,中的键NSDictionary等),甚至切换到-reverseObjectEnumerator向后枚举数组,而所有其他代码都没有更改。如果迭代码是一个方法,你甚至可以通过任何NSEnumerator和代码甚至不必关心什么它的迭代。此外,NSEnumerator只要有更多对象,(至少由Apple代码提供的)就保留它枚举的集合,因此您不必担心自动释放的对象将存在多长时间。
NSEnumerator(或快速枚举)保护您免受的最大伤害可能是在枚举时在您不知情的情况下在您的下面进行了可变的集合(数组或其他)更改。如果按索引访问对象,则可能会遇到奇怪的异常或异常错误(通常是在问题发生后很长时间),这很容易调试。使用一种标准习语进行枚举具有“快速失败”的行为,因此,当您在发生突变后尝试访问下一个对象时,该问题(由错误的代码引起)将立即显现出来。随着程序变得更加复杂和多线程,或者甚至依赖于第三方代码可能会修改的内容,脆弱的枚举代码变得越来越有问题。封装和抽象FTW!:-)
TA贡献1817条经验 获得超14个赞
对于OS X 10.4.x和更低版本:
int i;
for (i = 0; i < [myArray count]; i++) {
id myArrayElement = [myArray objectAtIndex:i];
...do something useful with myArrayElement
}
对于OS X 10.5.x(或iPhone)及更高版本:
for (id myArrayElement in myArray) {
...do something useful with myArrayElement
}
- 3 回答
- 0 关注
- 521 浏览
添加回答
举报