首页 文章

的NSOperation . 取消与完成状态

提问于
浏览
4

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

我有一个问题,甚至在队列上调用cancelAllOperations后,我的main方法挂在waitUntilAllOperationsAreFinished上 .

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

- (BOOL)isFinished
{
    return complete;
}

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

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

2 回答

  • 3

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

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

  • 4

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

    • 当您更改要完成的操作的状态时,您必须手动执行相应的 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也返回适当的值) . 如果您不这样做,您的操作可能永远不会完成 .

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

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

    • 如果你没有任何地方你可以定期检查取消状态,你想要覆盖 cancel 方法,它执行你需要的任何清理,调用 [super cancel] 但也确保操作也完成(例如,如果操作,请调用 completeOperation 正在执行) .

    我也有 start 检查取消状态:

    - (void)start
    {
        if ([self isCancelled]) {
            self.finished = YES;
            return;
        }
    
        self.executing = YES;
    
        // start my operation
    }
    

    除了上述内容之外,'s hard to counsel you further without knowing a bit more about what'在操作的核心( NSURLConnectionNSURLSession ?还有什么?) .

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

相关问题