completionBlock 究竟是在什么时候在 NSOperation 上执行的?

At which moment exactly is completionBlock executed on NSOperation?

我只是想知道在 NSOperationQueue 拥有的 NSOperation 上执行 completionBlock 的确切时刻。

在我的最新项目中,Amazon S3 的客户端 (https://github.com/StudioIstanbul/SIAFAWSClient),我使用带有 completionBlock 的 NSOperation 来请求 Amazon REST API。客户端能够通过主 class 上名为 isBusy 的 属性 监控所有计划请求的状态。在我的操作的完成块中,如果我的 NSOperationQueue 中没有安排其他操作,我将此 属性 的值设置为 NO。我现在发现,在极少数情况下,当调用 completionBlock 时,我当前的 NSOperation 仍包含在我的 NSOperationQueue 中。这对我来说似乎有点奇怪。我最终检查了我的队列中是否存在当前的 NSOperation 来解决这个问题,但从设计的角度来看这似乎是不必要的。

__weak AWSOperation* thisOperation = operation;
[operation setCompletionBlock:^{
    if (self.operationQueue.operationCount <= 0
      || (self.operationQueue.operationCount == 1
      && [self.operationQueue.operations objectAtIndex:0] == thisOperation)) {
        [self willChangeValueForKey:@"isBusy"];
        _isBusy = NO;
        [self didChangeValueForKey:@"isBusy"];
    }
}];

有人有关于此行为的更多信息吗?

来自文档:

The exact execution context for your completion block is not guaranteed but is typically a secondary thread. Therefore, you should not use this block to do any work that requires a very specific execution context.

因此,您不能保证它会在操作从队列中删除之前或之后被调用。它是在触发器之后发送的,用于从队列中删除操作(因为操作已完成),但实际上这两件事之间存在竞争。

如果您正在询问操作队列本身以确定状态,您最好的选择是将您的考虑推到主运行循环的下一次迭代。