I'm encountering some weird issues with some custom NSOperation
instances queued in an NSOperationQueue
instance:
When I call either [myOperation cancel]
or [myOperationQueue cancelAllOperations]
the isCancelled
getter for the cancel
boolean remains unchanged for my custom NSOperation
subclass instances.
I'm trying to cancel the operations when the app delegate applicationWillResignActive
method is called.
My implementation for NSOperation
subclass is like this:
- custom init method
- implemented main
I have a singleton with strong references to the instances of my NSOperation
subclass and NSOperationQueue
instance.
In a method of that singleton I do the following:
myNSOperationQueueInstance = [[NSOperationQueue alloc] init];
myCustomOperation_1 = [MyCustomOperationClass alloc] customInit];
myCustomOperation_2 = [MyCustomOperationClass alloc] customInit];
[myNSOperationQueueInstance addOperations:@[myCustomOperation_1,myCustomOperation_2] waitUntilFinished:NO];
Until now, everything works as expected, the custom operations start executing.
However, when I call another method of my singleton from applicationWillResignActive
to cancel my custom operations using either [myCustomOperation cancel]
or [myNSOperationQueueInstance cancelAllOperations]
the isCancelled
boolean remains unchanged (I check for isCancelled
periodically in the execution loop of my custom operations).
Another interesting thing is that in the same method which should cancel the operations, if I check with NSLog the isCancelled, isExecuting, isAsynchronous
the booleans are set to NO
but the isFinished
boolean is set to YES
even though the operations are executing at that time.
Also, if I try to see what operations are queued in my NSOperationQueue
using the operations
property, the array is empty.
If I override the cancel
property and its setter method of NSOperation
subclass, it works as expected.
I also requested a long running background task from the system which works just fine so the problem isn't that the app becomes inactive before the operations could cancel.
What am I missing? Why the isCancelled
getter doesn't change, why the operations
array property of NSOperationQueue
is empty despite the fact I added the operations and they're executing while interrogating the array and why the isFinished
boolean is set to YES
while the operations are executing?
Thanks to @KenThomases and @lead_the_zeppelin (see the comments in the OP) I was able to pinpoint the flaw in my code:
Since I created the custom
NSOperation
subclass to import data to a Core Data model, my flaw was that the code which performs the import called from the-main
method of the subclass, was embedded inside the scope of the block callback of the asynchronousperformBlock
method of theManagedObjectContext
that I am using to manage the import execution.So what happened was that the code inside
-main
was running asynchronously in another thread than my operation instance which, not surprisingly, was reporting that it finished its execution. In my case, to fix the issue, I changedperformBlock:
withperformBlockAndWait:
.Conclusion: if you ever encounter the same issues like me, check if the code running inside your custom
NSOperation
subclass-main
instance method doesn't run asynchronously.