can the nsblockoperation cancel itself while it is running thus canceling dependent nsoperations?

OK. I think I solved the mystery. I just misunderstood the [NSOperation cancel] documentation.

it says:

In macOS 10.6 and later, if an operation is in a queue but waiting on unfinished dependent operations, those operations are subsequently ignored. Because it is already cancelled, this behavior allows the operation queue to call the operation’s start method sooner and clear the object out of the queue. If you cancel an operation that is not in a queue, this method immediately marks the object as finished. In each case, marking the object as ready or finished results in the generation of the appropriate KVO notifications.

I thought that if operation B depends on operation A – it means that when A is canceled (hence – didn’t finish its work) then B should be cancelled as well – because semantically it can’t start until A completed its work.

That’s wishful thinking…

What the docs say is different. When you cancel B, then despite being dependent on A – it won’t wait for A to finish before it’s removed from the queue. If A hasn’t finished yet – canceling B will remove it quite immediately from the queue – because it’s still pending (the completion of A).

Soooo….. to accomplish my scheme, I will need to introduce my own “dependencies” mechanism, probably in the form of set of boolean properties like isPhotoTaken, isPhotoProcessed etc. and then an operation dependent on these, will need to check in its preamble (of execution block) whether all the required previous operations actually finished successfully.

It may be worth subclassing NSBlockOperation, overriding the logic that calls ‘start’ to skip to finished if any of the ‘dependencies’ has been cancelled… but that’s a long shot and may be hard to implement.

Finally, I wrote this quick subclass, and it seems to work – of course deeper inspection is due:

@interface MYBlockOperation : NSBlockOperation {
}
@end

@implementation MYBlockOperation
- (void)start {
    if ([[self valueForKeyPath:@"[email protected]"] intValue] > 0)
        [self cancel];
    [super start];
}
@end

When I substitute NSBlockOperation with MYBlockOperation in the original question (and my other tests, the behaviour is as the one I expected.

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top