How to undo NSOperation dependencies?

I have some NSOperation in the dependency graph:

 NSOperation *op1 = ...; NSOperation *op2 = ...; [op2 addDependency:op1]; 

Here's how I run them:

 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [queue addOperation:op1]; [queue addOperation:op2]; 

Now I need to cancel them. How can I guarantee that all NSOperation in the dependency graph will be canceled and that no other NSOperation will be canceled?


what i tried:

Calling cancel on NSOperation does not cancel the other (as far as I can tell):

 [op1 cancel]; // doesn't cancel op2 // -- or -- [op2 cancel]; // doesn't cancel op1 

Canceling a queue will also result in canceling operations that are not part of the dependency graph op1 and op2 (if there are such operations in the queue):

 [queue cancelAllOperations]; 

So I solved this with a custom method that recursively looks at NSOperation dependencies and undo them. However, I am not happy with this decision, because I feel that I am struggling with the framework:

 - (void)recursiveCancel:(NSOperation *)op { [op cancel]; for (NSOperation *dep in op.dependencies) { [self recursiveCancel:op]; } } 
+6
source share
2 answers

There is no concept of NSOperation that automatically NSOperation its dependencies. This is because several NSOperation may depend on the same other NSOperation . A dependency relationship exists strictly to delay the execution of a particular NSOperation until all of its NSOperation dependency has been NSOperation .

You can write a subclass of NSOperation :

 @interface NSOperationOneToOne : NSOperation - (void)addOneToOneDependency:(NSOperation *)operation; - (void)removeOneToOneDependency:(NSOperation *)operation; @end @implementation NSOperationOneToOne { NSMutableArray *oneToOneDependencies; } - (void)addOneToOneDependency:(NSOperation *)operation { [oneToOneDependencies addObject:operation]; [self addDependency:operation]; } - (void)removeOneToOneDependency:(NSOperation *)operation { [oneToOneDependencies removeObject:operation]; [self removeDependency:operation]; } - (void)cancel { [super cancel]; [oneToOneDependencies makeObjectsPerformSelector:@selector(cancel)]; } @end 

Note The above code is not guaranteed without errors.

+8
source

It sounds like you are trying to combine operations in one queue. To achieve this, it is best to split them using a queue for each group. Therefore, for each group, subclass NSOperation in parallel, turn on the queue, add each sub-operation to the queue. Cancel the cancellation and call [super cancel], then [self.queue cancelAllOperations].

The huge advantage of this approach is that you can repeat the operations, adding them back to the sub-queue without affecting the order of the main queue.

+1
source

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


All Articles