Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/116.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在iOS中具有进度报告的可取消异步操作集_Ios_Asynchronous_Progress_Operation_Cancellation - Fatal编程技术网

在iOS中具有进度报告的可取消异步操作集

在iOS中具有进度报告的可取消异步操作集,ios,asynchronous,progress,operation,cancellation,Ios,Asynchronous,Progress,Operation,Cancellation,假设我使用另一个SDK(我无法控制)和一个API,该API异步导入1个文件,并在完成时调用完成回调。 下面是一个示例API func importFile(filePath: String, completion: () -> Void) 我需要使用此API导入10个文件(一个接一个),但我需要它是可取消的,例如,在成功导入文件1、2、3后,在导入文件4时,我希望能够取消整个操作集(导入10个文件),这样文件4将完成(因为它已经启动),但文件5-10将不再导入 此外,我还需要报告导入的进

假设我使用另一个SDK(我无法控制)和一个API,该API异步导入1个文件,并在完成时调用完成回调。 下面是一个示例API

func importFile(filePath: String, completion: () -> Void)
我需要使用此API导入10个文件(一个接一个),但我需要它是可取消的,例如,在成功导入文件1、2、3后,在导入文件4时,我希望能够取消整个操作集(导入10个文件),这样文件4将完成(因为它已经启动),但文件5-10将不再导入

此外,我还需要报告导入的进度。成功导入文件1后,我应该报告10%的进度(10个中有1个已经完成)

我怎样才能做到这一点


我正在考虑将NSOperationQueue与10个NSOperations一起使用,但似乎进度报告会很困难。

NSOperationQueue
提供了一个很好的面向对象的抽象功能,这是我将采用的方法

  • 创建名为
    importQueue
每次进口:

  • 创建一个
    NSOperation
  • 存储要访问的操作,并可能在以后将其取消,例如在字典中[ImportNumber:NSOperation]
  • 将操作添加到
    importQueue

关于进展情况:

备选案文1:


NSOperationQueue
有一个名为
operations
的属性,您可以观察该属性的计数。(
importQueue.operations.count

备选案文2:

NSOperation
提供完成块。您可以在操作排队时增加计数器,在完成块内或取消时减少计数器



进一步阅读:,。

我认为您应该在您的操作上添加依赖项。 这个想法是:

1Op = NSOperation..
2Op = NSOperation..
.
.
10Op = NSOperation..

10Op.addDependency(9Op)
9Op.addDependency(8Op) and so on...
然后,您的操作子类应该以这种方式重写cancel方法

cancel() {
    super.cancel()
    for dep in dependencies {
        dep.cancel()
    }
}

所以,我相信这就是你想从你的问题中得到的:

  • 在队列中逐个导入n个文件
  • 导入每个文件时报告进度
  • 能够在中间取消操作
  • 可以通过以下方式使用
    NSOperationQueue
    NSBlockOperation
    实现

  • 根据以下StackOverflow问题的答案中给出的代码创建
    AsyncBlockOperation
    NSOperationQueue+AsyncBlockOperation
    类:
  • 将这两个类导入到它们将要使用的文件中
  • 创建一个操作队列

    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();
             }];
         }];
    }
    

  • 我自己也试过这个代码。它工作得很好。请随时提出改进建议:)

    请检查我的答案,并让我知道这是否是您想要的。事实上,我认为我们也可以使用
    dispatch\u suspend
    来解决此问题。您是否正在寻找仅基于NSOperation的解决方案?我对我的答案进行了编辑,使其能够回答您的所有查询。我谦恭地请你看一看。看起来不错。但是,如果importFile是异步的,如问题描述中所述,您会怎么做?那么,当所有操作都已完成时,完成回调如何处理该要求呢?我会在几分钟后补充说,如果进度为100,那么这意味着它是成功的。在这里,当您可以选择手动取消操作时,故障报告变得很困难。小疑问:如果其中一个文件导入失败,我们应该继续还是取消所有操作?此外,由于您的
    importFile
    函数是异步的,您可以使用NSOperationBlock代替正常的NSOperationBlock,因此您建议为NSOperation的子类使用异步类型的实现。谢谢您将如何为异步API实现NSOperation(如问题描述中所述)?具体的实现将太长,而且imo。因此不打算提供这一点。如果您在阅读本教程后有任何问题,请告知我们,可能是针对您遇到的特定新问题的新问题。简单的回答是可以的。问题明确指出API(来自第三方SDK)是异步的,您的答案使用同步API。NSO操作可以运行同步(或非并发)和异步(或并发)。所有这些都在所提到的教程中得到了很好的解释。您提到的教程中的NSO操作(ImageDownloader和ImageFiltering)仅使用同步API。您指的是什么异步API?进度报告和完成回调如何?在您的操作中,您可以调用进度更新委托
    [operationQueue cancelAllOperations];