有时候,你需要对数组中的每个对象进行操作。有时,这个数组可能非常大。有时,你希望执行的操作太慢,不能在主线程上枚举整个数组。通常,将数组枚举移到后台线程似乎是最好的解决方案。然而,这样的行为会带来技术和认知层面的开销。
ASMAsyncEnumeration 提供了另一种选择:在主线程(或任何你希望的调度队列)上执行枚举,允许运行循环在操作之间运行。
ASMAsyncEnumeration 并不影响代码运行的快慢。ASMAsyncEnumeration 不会神奇地使你的代码运行得更快。事实上,如果有的话,它甚至会使它变得更慢。然而,ASMAsyncEnumeration 的目的在于提供一个简单快捷的方式来执行长时间运行的操作,在这种操作中,速度并不那么重要,而且不必担心线程问题。
要运行示例项目,首先从 GitHub 上克隆仓库,然后从 Example 目录中运行 pod install
。
NSArray* array = ...; // some big array
[array asm_enumerateObjectsAsynchronouslyOnMainQueueUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(@"index: %@ value: %@", @(idx), obj);
}
completion:^(NSUInteger stoppedIndex, NSError* error) {
NSLog(@"Finished.");
}];
这将在主线程上执行枚举,每个循环迭代一次。它提供了多种方法,以提供不同级别的控制,包括在特定调度队列上运行,控制每次运行循环的步骤数,以及遍历指定的索引集。
枚举和完成块将在指定的调度队列上调用。
不建议使用可变数组。如果你必须使用 NSMutableArray,最好制作一个不可变的副本并替代使用。数组在枚举完成前会被保留,所以这个副本可以是临时的。
NSMutableArray* mutableArray = ...;
[mutableArray.copy asm_enumerateObjectsAsynchronouslyOnMainQueueUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(@"index: %@ value: %@", @(idx), obj);
}
completion:^(NSUInteger stoppedIndex, NSError* error) {
NSLog(@"Finished.");
}];
如果必须直接遍历可变数组,务必小心不要在枚举完成之前修改数组,否则结果将是不确定的。
ASMAsyncEnumeration 支持 NSProgress。
Andy Molloy,[email protected]
ASMAsyncEnumeration 在 MIT 许可证下可用。有关更多信息,请参阅 LICENSE 文件。