iPhone - return from an NSOperation

蓝咒 提交于 2019-12-11 14:45:24

问题


I am using a subclass of NSOperation to do some background processes. I want the operation to be cancelled when the user clicks a button.

Here's what my NSOperation subclass looks like

- (id)init{
    self = [super init];
    if(self){
        //initialization code goes here
        _isFinished = NO;
        _isExecuting = NO;
    }

    return self;
}

- (void)start
{
    if (![NSThread isMainThread])
    {
        [self performSelectorOnMainThread:@selector(start) withObject:nil waitUntilDone:NO];
        return;
    }
    [self willChangeValueForKey:@"isExecuting"];
    _isExecuting = YES;
    [self didChangeValueForKey:@"isExecuting"];

    //operation goes here
}

- (void)finish{
    //releasing objects here

    [self willChangeValueForKey:@"isExecuting"];
    [self willChangeValueForKey:@"isFinished"];

    _isExecuting = NO;
    _isFinished = YES;

    [self didChangeValueForKey:@"isExecuting"];
    [self didChangeValueForKey:@"isFinished"];
}

- (void)cancel{
    [self willChangeValueForKey:@"isCancelled"];

    [self didChangeValueForKey:@"isCancelled"];
    [self finish];
}

And this is how I am adding objects of this class to a queue and listening for KVO notifications

operationQueue = [[NSOperationQueue alloc] init]; [operationQueue setMaxConcurrentOperationCount:5]; [operationQueue addObserver:self forKeyPath:@"operations" options:0 context:&OperationsChangedContext];

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (context == &OperationsChangedContext) {
        NSLog(@"Queue size: %u", [[operationQueue operations] count]);
    }
    else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

To cancel an operation (on a button click for instance), I tried calling -cancel but it doesn't make a difference. Also tried calling -finish but even that doesn't change anything.

Every time I add an operation to the queue, the queue size only increases. finish is called (checked using NSLog statements) but it doesn't really end the operation. I'm still not very confident I'm doing this right

Can someone please tell me where I am going wrong?

Thanks a lot


回答1:


From the NSOperation Class Reference:

Cancelling an operation does not immediately force it to stop what it is doing. Although respecting the value returned by the isCancelled is expected of all operations, your code must explicitly check the value returned by this method and abort as needed.

i.e. the cancel method does not actually cancel the operation unless your implementation enforces this. Again, from the relevant section:

- (void)cancel

This method does not force your operation code to stop. Instead, it updates the object’s internal flags to reflect the change in state.




回答2:


You just need the following to achieve it:

In your NSOperation subclass, add to main method

 while (! self.isCancelled) {
  [NSThread sleepForTimeInterval:1];
 }

In the GUI class, you need an instance variable to your NSOperation subclass, and in the method that manages the button, you cancel your NSOperation subclass. For instance:

- (IBAction) clickButton: (UIBarButtonItem *) item{
 [myOperation cancel]; 
}


来源:https://stackoverflow.com/questions/1770529/iphone-return-from-an-nsoperation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!