Pau*_*ler 150 multithreading objective-c ios4 objective-c-blocks
除了明显的差异:
enumerateObjectsUsingBlock时,你既需要索引和对象enumerateObjectsUsingBlock当你需要修改局部变量时不要使用被enumerateObjectsUsingBlock普遍认为是好还是坏的时候for (id obj in myArray)也将工作?有哪些优点/缺点(例如性能或多或少)?
bbu*_*bum 347
最终,使用您想要使用的模式,并在上下文中更自然地使用.
虽然for(... in ...)非常方便且语法简洁,enumerateObjectsUsingBlock:但有许多功能可能会或可能不会很有趣:
enumerateObjectsUsingBlock:将比快速枚举更快或更快(for(... in ...)使用NSFastEnumeration支持实现枚举).快速枚举需要从内部表示转换为快速枚举的表示.其中有开销.基于块的枚举允许集合类以最快遍历本机存储格式的速度枚举内容.可能与数组无关,但它对于字典来说可能是一个巨大的差异.
"当你需要修改局部变量时,不要使用enumerateObjectsUsingBlock" - 不是真的; 你可以声明你的本地人__block,他们将在街区中可写.
enumerateObjectsWithOptions:usingBlock: 支持并发或反向枚举.
使用词典,基于块的枚举是同时检索键和值的唯一方法.
就个人而言,我enumerateObjectsUsingBlock:经常使用for (... in ...),但是 - 再次 - 个人选择.
Chu*_*uck 81
对于简单的枚举,简单地使用快速枚举(即for…in…循环)是更惯用的选项.块方法可能稍微快一些,但在大多数情况下这并不重要 - 很少有程序受CPU限制,即使这样,循环本身而不是内部计算也很少成为瓶颈.
一个简单的循环也读得更清楚.这是两个版本的样板:
for (id x in y){
}
[y enumerateObjectsUsingBlock:^(id x, NSUInteger index, BOOL *stop){
}];
Run Code Online (Sandbox Code Playgroud)
即使您添加一个变量来跟踪索引,简单循环也更容易阅读.
所以什么时候应该使用enumerateObjectsUsingBlock:?当您存储块以便稍后执行或在多个位置执行时.当你实际上使用一个块作为一流函数而不是一个循环体的过度替代时,这是很好的.
Ada*_*lan 42
虽然这个问题很老,但事情没有改变,接受的答案是不正确的.
该enumerateObjectsUsingBlockAPI并不意味着取代for-in,但对于一个完全不同的使用情况:
withOptions:参数)for-in仍然是枚举集合的惯用方法.快速枚举可以从简洁的代码,可读性和额外的优化中受益,这使得它非常快速.比旧的C for循环更快!
快速测试得出的结论是,2014年iOS 7上的enumerateObjectsUsingBlock速度始终比for-in慢700%(基于100项阵列的1mm迭代).
表演在这里真的是一个实际问题吗?
绝对不是,罕见的例外.
关键是要证明enumerateObjectsUsingBlock:在for-in没有充分理由的情况下使用过程几乎没有什么好处.它不会使代码更具可读性......或者更快......或者是线程安全的.(另一种常见的误解).
选择取决于个人偏好.对我来说,惯用和可读的选项赢了.在这种情况下,即使用快速枚举for-in.
NSMutableArray *arr = [NSMutableArray array];
for (int i = 0; i < 100; i++) {
arr[i] = [NSString stringWithFormat:@"%d", i];
}
int i;
__block NSUInteger length;
i = 1000 * 1000;
uint64_t a1 = mach_absolute_time();
while (--i > 0) {
for (NSString *s in arr) {
length = s.length;
}
}
NSLog(@"For-in %llu", mach_absolute_time()-a1);
i = 1000 * 1000;
uint64_t b1 = mach_absolute_time();
while (--i > 0) {
[arr enumerateObjectsUsingBlock:^(NSString *s, NSUInteger idx, BOOL *stop) {
length = s.length;
}];
}
NSLog(@"Enum %llu", mach_absolute_time()-b1);
Run Code Online (Sandbox Code Playgroud)
结果:
2014-06-11 14:37:47.717 Test[57483:60b] For-in 1087754062
2014-06-11 14:37:55.492 Test[57483:60b] Enum 7775447746
Run Code Online (Sandbox Code Playgroud)
Lea*_*s2D 23
为了回答有关性能的问题,我使用我的性能测试项目进行了一些测试.我想知道向数组中的所有对象发送消息的三个选项中哪一个是最快的.
选项是:
1)makeObjectsPerformSelector
[arr makeObjectsPerformSelector:@selector(_stubMethod)];
Run Code Online (Sandbox Code Playgroud)
2)快速枚举和定期发送消息
for (id item in arr)
{
[item _stubMethod];
}
Run Code Online (Sandbox Code Playgroud)
3)enumerateObjectsUsingBlock®ular message send
[arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{
[obj _stubMethod];
}];
Run Code Online (Sandbox Code Playgroud)
事实证明,makeObjectsPerformSelector是迄今为止最慢的.它花费的时间是快速枚举的两倍.而enumerateObjectsUsingBlock是最快的,它比快速迭代快15-20%.
因此,如果您非常关注最佳性能,请使用enumerateObjectsUsingBlock.但请记住,在某些情况下,枚举集合所花费的时间与运行您希望每个对象执行的任何代码所花费的时间相比是相形见绌的.