0

Is it right if I cancel an NSInvocationOperation inside the operation? example:

.h file:

//defined in the interface
NSInvocationOperation *op1;
NSOperationQueue  *loadQueue;

.m file:

-(id)init{
    op1 = [NSInvocationOperation new];
    loadQueue = [NSOperationQueue new];
}

-(void)downloadData{
    op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(loadServerResponse:) object:newerRequest];
    [loadQueue addOperation:op1];
}

Now I have a method to download data from the server. I added a condition to check if there is an error. If so I'm cancelling that operation inside the method and calling back the same method upon retrieving the new login token.

- (void)loadServerResponse{
    if(server_error){
        [op1 cancel];
        //fetch login token again
        [self downloadData];
        return;
    }

Am I doing anything wrong?

Mike S
  • 41,895
  • 11
  • 89
  • 84
Siddharthan Asokan
  • 4,321
  • 11
  • 44
  • 80

1 Answers1

1

First, referencing op1 (which I'm assuming is a class-level ivar) is a Bad Thing™ on multiple levels, the first of which is NSOperationQueue dispatches your operation onto a background thread, so op1 will (at best) be copied into that thread's context and no longer reference the original operation you were attempting to cancel.

I think you don't need to worry about canceling the operation, given the logic you have shared. You specifically seem to want to call downloadData after canceling, and there's no guarantee that will happen if you cancel the operation first. I would just remove the call to cancel the operation, and continue on. Normally you only cancel a running operation from an external source (say if you receive a notification that your application will enter background state).

Matt S.
  • 1,882
  • 13
  • 17
  • if what you said is true then how could one ever access a NSInvocationOperation object and call cancel on it (or any other method) ? – 2cupsOfTech May 01 '15 at 20:49
  • A good question - in this specific example the OP was trying to cancel from within the method that the operation was attempting to execute. This means that he/she was attempting to reference an object across thread boundaries, which is generally considered a bad idea. If you want to call cancel, you should call it from the original thread that enqueued the operation, OR subclass NSOperation and manage it internally. – Matt S. May 01 '15 at 23:42
  • that makes sense. I am doing something similar but my cancel happens from outside (not from the method-to-execute) and I think that should be fine to do. I handle isCancelled within the method-to-execute – 2cupsOfTech May 02 '15 at 14:45