for(... in ...) or enumerateObjectsUsingBlock
Xcode 11.2.1
iPhone 8 13.2.2 模拟器
只遍历所有对象
NSMutableArray *myArr = [[NSMutableArray alloc] init];
for (int i = 0; i < 10000; i ++) {
[myArr addObject:[NSNumber numberWithInt:i]];
}
NSDate *date0 = [[NSDate alloc] init];
[myArr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
}];
NSLog(@"enum %lf", [[[NSDate alloc] init] timeIntervalSinceDate:date0]);
date0 = [[NSDate alloc] init];
for (NSNumber *num in myArr) {
}
NSLog(@"for in %lf", [[[NSDate alloc] init] timeIntervalSinceDate:date0]);
for/in0.000044enumerateObjectsUsingBlock0.000495
遍历对象并执行耗时操作
NSDate *date0 = [[NSDate alloc] init];
[myArr enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[self consumeSomeTime];
}];
NSLog(@"enum %lf", [[[NSDate alloc] init] timeIntervalSinceDate:date0]);
date0 = [[NSDate alloc] init];
for (NSNumber *num in myArr) {
[self consumeSomeTime];
}
NSLog(@"for in %lf", [[[NSDate alloc] init] timeIntervalSinceDate:date0]);
for/in0.156068enumerateObjectsUsingBlock0.026496
结论
- 一般情况下,
for/in要比enumerateObjectsUsingBlock快; - 但是,针对于可并发执行的情形,
enumerateObjectsUsingBlock原生支持并发操作,明显耗时更短。
另外,上述并发,也可用dispatch_apply实现。
dispatch_apply([myArr count], dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^(size_t index) {
[self consumeSomeTime];
});
其实,通过断点也可发现,NSEnumerationConcurrent 内部也是通过 dispatch_apply 实现的。

相关阅读:
NSFastEnumeration / NSEnumerator
When to use enumerateObjectsUsingBlock vs. for