ios - iOS 中带有进度报告的可取消异步操作集

标签 ios asynchronous progress operation cancellation

假设我使用另一个 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 一起使用,但似乎很难报告进度。

最佳答案

因此,我相信这是您希望从问题中得到的以下信息:

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

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

  1. 根据以下 StackOverflow 问题的答案中给出的代码创建 AsyncBlockOperationNSOperationQueue+AsyncBlockOperation 类:NSOperation wait until asynchronous block executes
  2. 将这两个类导入到它们将要使用的文件中
  3. 创建一个操作队列

    NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
    operationQueue.maxConcurrentOperationCount = 1;
    operationQueue.name = @"com.yourOrganization.yourProject.yourQueue";
    
  4. 创建一个函数,为您提供获取进度的回调

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

    中执行您的操作
    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. 对于取消操作,我们可以简单地使用我们在第一步中创建的operationQueue

    [operationQueue cancelAllOperations];
    

我自己试过这段代码。它运作良好。随时提出改进建议,使其变得更好:)

关于ios - iOS 中带有进度报告的可取消异步操作集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40265055/

相关文章:

c# - 具有异步表单工厂的简单注入(inject)器

Python3 与 asyncpg 的语法错误

java - 如何确定DataHandler.writeTo()方法当前写入的字节数?

javascript - ajax 后上传进度 - 仅限客户端

ios - AFHTTPSessionManager 忽略 HTTPMaximumConnectionsPerHost

ios - 将选择器传递给自定义方法以编程方式创建 UIButton

c# - 同时运行 x 个 Web 请求

Java:显示进度监视器和子进度监视器的进度

ios - Iphone App 拒绝 Ipv6 不兼容

ios - 从自定义 TableViewCell 中的 didSelectItemAt 自定义 CollectionViewCell 更改 View Controller