首页 文章

NSOperation completionBlock被调用两次

提问于
浏览
4

我正在研究一个NSOperation子类,我遇到了这个非常奇怪的问题,连续两次调用完成块 . KVO调用似乎很好但是completionBlock仍然被奇怪地调用了两次 . 我误解了NSOperation吗?文档说当 isFinished 成为 YES 并且只在我的代码中发生一次时调用完成块:

- (void)main {
    @autoreleasepool {
        [self willChangeValueForKey:@"isExecuting"];
        [self willChangeValueForKey:@"isReady"];
        executing = YES;
        [self didChangeValueForKey:@"isReady"];
        [self didChangeValueForKey:@"isExecuting"];

        //start the operation
    }
}

然后我就像这样设置 completionBlock

self.completionBlock = ^{
    NSLog(@"Completed");
}

当它完成时,这个方法被调用(它被称为ONCE,我仔细检查过)

- (void)completeOperation {
    [self willChangeValueForKey:@"isExecuting"];
    [self willChangeValueForKey:@"isFinished"];
    executing = NO;
    completed = YES;
    [self didChangeValueForKey:@"isExecuting"];
    [self didChangeValueForKey:@"isFinished"];
}

但是,completionBlock被调用两次,并在控制台中两次打印“Completed” .

以下是指示当前状态的方法:

- (BOOL)isReady {
    if (executing || cancelled || completed) {
        return NO;
    }
    return YES;
}
- (BOOL)isCancelled {
    return cancelled;
}

- (BOOL)isConcurrent {
    return YES;
}

- (BOOL)isExecuting {
    return executing;
}

- (BOOL)isFinished {
    return completed;
}

isCancelled 永远不会在我的测试代码中转向 YES ,因此不能成为它的原因 .

我真的不明白为什么completeBlock被调用两次 . 即使从完成块内部将完成块设置为nil,有时也会被称为两次,这甚至更奇怪 .

1 回答

  • 4

    不确定这是否是原因,但根据我的经验,不需要覆盖只读状态属性 . 你负责在主循环中定期检查isCancelled,如果它被设置为无法正常运行,但我相信其他状态标志(isReady,isFinished,isExecuting)会自动处理 .

    如果您剥离状态标志处理并在 -main 中执行您的过程,它会触发多少次?

    编辑:假设你重写那些标志以允许并发,那么你应该通读笔记in the docs

    根据它的外观,您永远不需要覆盖 isReadyisCancelled ,而是根据文档中的说明覆盖 -start .

相关问题