在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,但是进度报告似乎很难。

所以,我相信这是你想从你的问题以下:

  1. 在队列中逐个导入n个文件
  2. 报告每个文件导入时的进度
  3. 能够取消中间的操作

这可以通过以下方式使用NSOperationQueueNSBlockOperation来实现。

  1. 创buildAsyncBlockOperationNSOperationQueue+AsyncBlockOperation类的答案中给出的答案为下面的StackOverflow问题: NSOperation等到asynchronous块执行
  2. 将两个类都导入到将要使用的文件中
  3. 创build一个操作队列

     NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; operationQueue.maxConcurrentOperationCount = 1; operationQueue.name = @"com.yourOrganization.yourProject.yourQueue"; 
  4. 创build一个函数,让你获得进步的callback

     - (void)importFilesFromFilePathArray:(NSArray *)pathsArray inOperationQueue:(NSOperationQueue *)operationQueue withProgress:(void (^)(CGFloat progress))progressBlock { } 
  5. 2定义的函数内部,使用NSBlockOperationNSBlockOperation中执行操作

     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(); }]; }]; } 
  6. 对于取消操作,我们可以简单地使用我们在第一步创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操作,为什么,如何 , 好,但老式的教程 。

Interesting Posts