请使用以下代码
NSMutableArray *array = [NSMutableArray new];
for (int i = 0; i < 10000; i++) {
[array addObject:@(i)];
}
queue1 = dispatch_queue_create("com.test_enumaration.1", DISPATCH_QUEUE_CONCURRENT);
queue2 = dispatch_queue_create("com.test_enumaration.2", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue1, ^{
int idx = 0;
for (NSNumber *obj in array) {
NSLog(@"[%d] %@", idx, obj);
idx++;
}
});
double delayInSeconds = 0.3;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, queue2, ^(void){
[array removeObjectAtIndex:9000];
NSLog(@"----");
});
我希望这段代码会崩溃,因为在某个时刻分派到
queue2
的块与枚举同时执行,这将触发断言,即在枚举时不能改变数组。事实上,这就是发生的事情。有趣的部分是当您用
enumerateObjectsUsingBlock:
替换for ( in )
时。NSMutableArray *array = [NSMutableArray new];
for (int i = 0; i < 10000; i++) {
[array addObject:@(i)];
}
queue1 = dispatch_queue_create("com.test_enumaration.1", DISPATCH_QUEUE_CONCURRENT);
queue2 = dispatch_queue_create("com.test_enumaration.2", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue1, ^{
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(@"[%d] %@",idx, obj);
}];
});
double delayInSeconds = 0.3;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, queue2, ^(void){
[array removeObjectAtIndex:9000];
NSLog(@"----");
});
在我进行的各种测试中,删除对象的块在枚举的中间被执行(我看到了"----"的印刷品),有趣的是,枚举行为正确,打印出[8999] 8999,然后是[9000] 9001。 在这种情况下,在枚举期间改变数组,而不触发任何断言。这是一种预期的行为吗?如果是,为什么?我有遗漏什么吗?