我知道,如果您有一个修改循环中项目计数的循环,那么在集合上使用NSEnumerator是确保代码爆炸的最好方法,但是我想了解一下NSEnumerator类和一个旧的for循环之间的性能权衡。
发布于 2008-08-28 19:59:49
在Objective-C2.0中使用新的for (... in ...)语法通常是迭代集合的最快方法,因为它可以在堆栈上维护一个缓冲区,并将成批的项放入其中。
使用NSEnumerator通常是最慢的方式,因为它经常复制要迭代的集合;对于不可变的集合,这可能很便宜(相当于-retain),但对于可变的集合,它可能会导致创建不可变的副本。
进行自己的迭代-例如,使用-[NSArray objectAtIndex:] -通常介于两者之间,因为虽然您不会有潜在的复制开销,但您也不会从底层集合中获得批量对象。
(PS -这个问题应该标记为Objective-C,而不是C,因为NSEnumerator是一个Cocoa类,并且新的for (... in ...)语法特定于Objective-C。)
发布于 2015-06-09 06:47:16
在多次运行测试之后,结果几乎相同。每个测量块连续运行10次。
在我的例子中,结果从最快到最慢:
testPerformanceExample3()testPerformanceExample4 (testPerformanceExample2) (0.067 #en4#
for和while循环几乎是相同的。

tmp是一个NSArray,它包含从0到999999的100万个对象。
- (NSArray *)createArray
{
self.tmpArray = [NSMutableArray array];
for (int i = 0; i < 1000000; i++)
{
[self.tmpArray addObject:@(i)];
}
return self.tmpArray;
}完整的代码:
ViewController.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (strong, nonatomic) NSMutableArray *tmpArray;
- (NSArray *)createArray;
@endViewController.m
#import "ViewController.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self createArray];
}
- (NSArray *)createArray
{
self.tmpArray = [NSMutableArray array];
for (int i = 0; i < 1000000; i++)
{
[self.tmpArray addObject:@(i)];
}
return self.tmpArray;
}
@endMyTestfile.m
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import "ViewController.h"
@interface TestCaseXcodeTests : XCTestCase
{
ViewController *vc;
NSArray *tmp;
}
@end
@implementation TestCaseXcodeTests
- (void)setUp {
[super setUp];
vc = [[ViewController alloc] init];
tmp = vc.createArray;
}
- (void)testPerformanceExample1
{
[self measureBlock:^{
for (int i = 0; i < [tmp count]; i++)
{
[tmp objectAtIndex:i];
}
}];
}
- (void)testPerformanceExample2
{
[self measureBlock:^{
[tmp enumerateObjectsUsingBlock:^(NSNumber *obj, NSUInteger idx, BOOL *stop) {
obj;
}];
}];
}
- (void)testPerformanceExample3
{
[self measureBlock:^{
for (NSNumber *num in tmp)
{
num;
}
}];
}
- (void)testPerformanceExample4
{
[self measureBlock:^{
int i = 0;
while (i < [tmp count])
{
[tmp objectAtIndex:i];
i++;
}
}];
}
@end欲了解更多信息,请访问:Apples "About Testing with Xcode"。
发布于 2008-08-28 18:37:28
它们非常相似。在Objective-C2.0中,大多数枚举现在默认为NSFastEnumeration,它为集合中的每个对象创建一个地址缓冲区,然后它可以交付该缓冲区。与传统的for循环相比,您节省的一个步骤是不必每次在循环内调用objectAtIndex:i。您正在枚举的集合的内部实现快速枚举,而不调用objectAtIndex:i method。
缓冲区是您不能在枚举时改变集合的部分原因,对象的地址将会更改,构建的缓冲区将不再匹配。
作为额外的好处,2.0中的格式看起来和经典的for循环一样好:
for ( Type newVariable in expression ) {
stmts
}请阅读以下文档以深入了解:NSFastEnumeration Protocol Reference
https://stackoverflow.com/questions/32986
复制相似问题