在iOS中使用进度报告取消一组asynchronous操作
假设我使用另一个SDK(我没有控制权)与asynchronous导入1个文件的API,并在完成时调用完成callback。 以下是一个示例API。
func importFile(filePath: String, completion: () -> Void)
我需要使用此API导入10个文件(一个接一个),但我需要它是可取消的,例如,在成功导入文件1,2,3后,导入文件4时,我希望能够取消整个操作(导入10个文件),这样文件4将完成(因为它已经开始),但是文件5-10不会被导入。
另外,我还需要汇报import情况。 当文件1导入成功时,我应该报告10%的进度(十分之一已经完成)。
我怎样才能做到这一点?
我正在考虑使用NSOperationQueue和10个NSOperations,但是进度报告似乎很难。
所以,我相信这是你想从你的问题以下:
- 在队列中逐个导入n个文件
- 报告每个文件导入时的进度
- 能够取消中间的操作
这可以通过以下方式使用NSOperationQueue
和NSBlockOperation
来实现。
- 创build
AsyncBlockOperation
和NSOperationQueue+AsyncBlockOperation
类的答案中给出的答案为下面的StackOverflow问题: NSOperation等到asynchronous块执行 - 将两个类都导入到将要使用的文件中
-
创build一个操作队列
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; operationQueue.maxConcurrentOperationCount = 1; operationQueue.name = @"com.yourOrganization.yourProject.yourQueue";
-
创build一个函数,让你获得进步的callback
- (void)importFilesFromFilePathArray:(NSArray *)pathsArray inOperationQueue:(NSOperationQueue *)operationQueue withProgress:(void (^)(CGFloat progress))progressBlock { }
-
在
2
定义的函数内部,使用NSBlockOperation
在NSBlockOperation
中执行操作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(); }]; }]; }
-
对于取消操作,我们可以简单地使用我们在第一步创build的
operationQueue
[operationQueue cancelAllOperations];
我自己试过这个代码。 它运作良好。 随意build议改进,使其更好:)
我认为你应该增加对你的操作的依赖。 这个想法是这样的:
1Op = NSOperation.. 2Op = NSOperation.. . . 10Op = NSOperation.. 10Op.addDependency(9Op) 9Op.addDependency(8Op) and so on...
那么你的操作子类应该以这种方式重写取消方法
cancel() { super.cancel() for dep in dependencies { dep.cancel() } }
NSOperationQueue
提供了一个很好的面向对象的抽象,是我将走的路。
- 创build一个名为
importQueue
对于每个导入:
- 创build一个
NSOperation
- 存储操作到后来可能会被刷新,比如在一个字典中[ImportNumber:NSOperation]
- 将操作添加到
importQueue
关于进展状况:
选项1:
NSOperationQueue
有一个叫做operations
的属性,你可以观察这个属性。 ( importQueue.operations.count
)。
选项2:
NSOperation
提供完成块。 您可以在排队操作时增加计数器,并在完成块内或取消时减less计数器。
进一步阅读: 苹果文档 , asynchronous操作,为什么,如何 , 好,但老式的教程 。