的NSOperation。取消与完成状态

时间:2014-06-19 00:35:42

标签: ios objective-c macos nsoperation nsoperationqueue

我有一个带有NSOperationQueue的NSOperation,它有一堆子操作,有些是排队的。

我遇到了一个问题,即使在队列上调用cancelAllOperations后,我的main方法仍挂在waitUntilAllOperationsAreFinished上。

然后,当我设置完成标志时,我在取消时使用isFinished,它不再在取消的队列中备份。

- (BOOL)isFinished
{
    return complete;
}

- (void)cancel
{
    cancelled = YES;
    complete = YES;
    [_childOperationQueue cancelAllOperations];
}

这是正确的行为,取消的操作应该在技术上完成吗? 似乎NSOperation需要将isFinished设置为true才能将其删除,因为这可能会让它“清理”,但我不知道这里的协议是什么,谷歌没有透露太多。 / p>

2 个答案:

答案 0 :(得分:4)

取消操作只需设置isCancelled即可返回YES。这意味着在您的NSOperation块中,您可以检查isCancelled并防止不必要地执行任何工作(您需要自己实现此逻辑)。

您的主线程需要等待队列中的所有操作,但如果您的NSOperation块在执行任何操作之前检查isCancelled,您应该快速完成所有排队操作,并且等待不应该很长

答案 1 :(得分:3)

如果您正在编写并发操作(即isConcurrent方法返回YES),我有两个观察结果:

  1. 当您更改要完成的操作状态时,您必须手动执行相应的isFinished KVN。因此,在更改状态变量之前,请致电willChangeValueForKey,然后在更改后调用didChangeValueForKey

    有很多方法可以实现这一点,但我定义了finishedexecuting属性,如下所示:

    @property (nonatomic, readwrite, getter = isFinished)  BOOL finished;
    @property (nonatomic, readwrite, getter = isExecuting) BOOL executing;
    

    我使用那些合成的getter,但写了做适当KVN的setter:

    @synthesize finished  = _finished;
    @synthesize executing = _executing;
    
    - (void)setExecuting:(BOOL)executing
    {
        if (_executing != executing) {
            [self willChangeValueForKey:@"isExecuting"];
            _executing = executing;
            [self didChangeValueForKey:@"isExecuting"];
        }
    }
    
    - (void)setFinished:(BOOL)finished
    {
        if (_finished != finished) {
            [self willChangeValueForKey:@"isFinished"];
            _finished = finished;
            [self didChangeValueForKey:@"isFinished"];
        }
    }
    

    然后,当我想完成操作时,我调用一个这样的方法:

    - (void)completeOperation
    {
        self.executing = NO;
        self.finished = YES;
    }
    

    这导致isExecutingisFinished的KVN(以及确保我的合成getter也返回适当的值)。如果您不这样做,您的操作可能永远不会完成。

  2. 在取消操作方面,有两种方法:

    • 您可以定期检查[self isCancelled](一种非常常见的模式,如果你有一个循环或一些被重复调用的方法,例如基于委托的连接/会话中的didReceiveData),如果是这样,做你需要的任何清理,然后完成操作(上面的completeOperation方法)。

    • 如果您没有任何地方可以定期检查取消状态,您希望覆盖cancel方法,该方法会执行您需要的任何清理工作,请拨打[super cancel]但是还确保操作也完成(例如,如果操作正在执行,则调用completeOperation。)

    我还start检查取消状态:

    - (void)start
    {
        if ([self isCancelled]) {
            self.finished = YES;
            return;
        }
    
        self.executing = YES;
    
        // start my operation
    }
    
  3. 除此之外,如果不了解操作的核心内容(NSURLConnectionNSURLSession?还有什么其他内容,很难再为您提供建议? )。

    有关详细信息,请参阅Concurrency Programming Guide: Operation Queues中的配置并发执行操作