Cancel a set of asynchronous operations with progress reports in iOS

Suppose I use a different SDK (with which I have no control) with an API that imports 1 file asynchronously and causes completion to complete. The following is an example API.

func importFile(filePath: String, completion: () -> Void)

I need to import 10 files (one by one) using this API, but I need to cancel it, for example. after files 1,2,3 were successfully imported while file 4 is being imported, I want to be able to undo the whole set of operations (import of 10 files) so that file 4 is completed (since it is already running), but Files 5-10 will no longer be imported.

In addition, I also need to report on the progress of the import. When file 1 was successfully imported, I should report 10% progress (1 out of 10 completed).

How can i achieve this?

I am considering using NSOperationQueue with 10 NSOperations, but it seems like a progress report will be difficult.

+4
source share
3 answers

So, I believe that from your question you follow as follows:

  • Import n files in turn in a queue
  • Report import progress of each file
  • Ability to cancel the operation in the middle

This can be achieved using NSOperationQueueand NSBlockOperationas follows.

  • Create classes AsyncBlockOperationand NSOperationQueue+AsyncBlockOperationfrom the code given in the answer to the following StackOverflow question: NSOperation wait while the asynchronous block is running
  • Import both classes into a file that they will use
  • Create an operation queue

    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];
    

. . , :)

+1

NSOperationQueue - .

  • NSOperationQueue importQueue

:

  • NSOperation
  • , , , , , [ImportNumber: NSOperation]
  • importQueue

:

1:

NSOperationQueue , operations, , , . (importQueue.operations.count).

2:

NSOperation . .


: Apple, asynchronous-nsoperation-why-and-how, , .

0

, . :

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

10Op.addDependency(9Op)
9Op.addDependency(8Op) and so on...

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

Source: https://habr.com/ru/post/1658949/


All Articles