NSOperation 取消和 NSOperationQueue

NSOperation cancel and NSOperationQueue

我想了解 NSOperation 子类的正确行为是什么。 我的子类具有不同的 isReady 条件。是的,如果操作被取消,我会检查代码并据此采取行动。当操作正在执行时,这很好。它停止其任务,将 finished 设置为 true 并从队列中删除。但是它的依赖关系呢?它们尚未执行,因此它们永远处于 NSOperationQueue in cancelled 状态。

我是否应该为取消的操作设置 ready = true 以便队列将调用将在执行中设置的 start 方法并立即完成任务设置 finished 为真?

将执行相关操作。不管a是否取消。

您应该将 operation.finished==true 设置为最终状态以使 NSOperationQueue 删除 operation

您应该在准备好开始 operation 时设置 .ready==true

operation的生命周期中,你应该经常检查.cancelled每当.cancelled == true,你应该停止operation并设置.finished == true

我刚刚自己处理了这个问题。我不明白为什么当我取消我的 NSOperation 子类时,它从未从 NSOperationQueue 中删除。事实证明,我的重写 isReady 方法是罪魁祸首。 isReady 方法正在检查超级实现以及是否设置了 属性,但它没有,这就是操作被取消的原因。但是,显然,如果 NSOperation 实例从未达到就绪状态,即使它被取消,NSOperationQueue 也不会删除该操作,直到达到就绪状态。因此,解决方案是使用 isCancelled 属性 值对您自定义的准备就绪条件进行或运算。或者,您可以更改逻辑,使操作始终准备就绪,但如果未满足就绪条件,则在 main 方法中不执行任何操作,具体取决于您的应用程序逻辑。

示例:

// for proper KVO compliance
+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key
{
    NSSet *keys = [super keyPathsForValuesAffectingValueForKey:key];

    NSString *readyKey = NSStringFromSelector(@selector(isReady));
    if ([readyKey isEqualToString:key]) {
        keys = [keys setByAddingObjectsFromArray:@[NSStringFromSelector(@selector(url)), NSStringFromSelector(@selector(isCancelled))]];
    }

    return keys;
}

- (BOOL)isReady
{
    return (this.url != nil || this.isCancelled) && super.isReady;
}

- (void)setUrl:(NSURL *)url
{
    if (self.url == url) {
        return;
    }

    NSString *urlKey = NSStringFromSelector(@selector(url));

    [self willChangeValueForKey:urlKey];

    _url = url;

    [self didChangeValueForKey:urlKey];
}

感谢NSHipster的KVO article提供以上KVO相关代码