假设我使用另一个 SDK(我无法控制)和一个异步导入 1 个文件的 API,并在完成时调用完成回调。 以下是一个示例 API。
func importFile(filePath: String, completion: () -> Void)
我需要使用此 API 导入 10 个文件(一个接一个),但我需要它是可取消的,例如在文件 1、2、3 成功导入后,在导入文件 4 时,我希望能够取消整套操作(导入 10 个文件),这样文件 4 就会完成(因为它已经开始), 但文件 5-10 将不再导入。
此外,我还需要报告导入进度。成功导入文件 1 后,我应该报告 10% 的进度(10 个中的 1 个已完成)。
我怎样才能做到这一点?
我正在考虑将 NSOperationQueue 与 10 个 NSOperations 一起使用,但似乎很难报告进度。
最佳答案
因此,我相信这是您希望从问题中得到的以下信息:
- 在队列中逐一导入n个文件
- 导入每个文件时报告进度
- 能够在中间取消操作
可以通过以下方式使用NSOperationQueue
和NSBlockOperation
来实现。
- 根据以下 StackOverflow 问题的答案中给出的代码创建
AsyncBlockOperation
和NSOperationQueue+AsyncBlockOperation
类:NSOperation wait until asynchronous block executes - 将这两个类导入到它们将要使用的文件中
创建一个操作队列
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; operationQueue.maxConcurrentOperationCount = 1; operationQueue.name = @"com.yourOrganization.yourProject.yourQueue";
创建一个函数,为您提供获取进度的回调
- (void)importFilesFromFilePathArray:(NSArray *)pathsArray inOperationQueue:(NSOperationQueue *)operationQueue withProgress:(void (^)(CGFloat progress))progressBlock { }
在
中执行您的操作2
中定义的函数内,使用NSBlockOperation
在NSOperationQueue
for (int i = 0; i < pathsArray.count; i++) { [operationQueue addAsyncOperationWithBlock:^(dispatch_block_t completionHandler) { [self importFile:(NSString *)[pathsArray objectAtIndex:i] completion:^(bool completion) { [[NSOperationQueue mainQueue] addOperationWithBlock:^{ CGFloat progress = (100 * (float)(i+1)/pathsArray.count); progressBlock(progress); if (progress == 100) { successBlock(YES); } }]; completionHandler(); }]; }]; }
对于取消操作,我们可以简单地使用我们在第一步中创建的
operationQueue
[operationQueue cancelAllOperations];
我自己试过这段代码。它运作良好。随时提出改进建议,使其变得更好:)
关于ios - iOS 中带有进度报告的可取消异步操作集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40265055/