Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/104.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios NSOperation completionBlock被调用两次_Ios_Objective C_Nsoperation_Completion Block - Fatal编程技术网

Ios NSOperation completionBlock被调用两次

Ios NSOperation completionBlock被调用两次,ios,objective-c,nsoperation,completion-block,Ios,Objective C,Nsoperation,Completion Block,我正在处理一个NSOperation子类,我遇到了一个非常奇怪的问题,完成块被连续调用了两次。KVO调用看起来不错,但completionBlock仍然奇怪地被调用了两次。我是不是误解了手术?文档中说,当isFinished变为YES时,会调用完成块,并且在我的代码中只发生一次: - (void)main { @autoreleasepool { [self willChangeValueForKey:@"isExecuting"]; [self will

我正在处理一个NSOperation子类,我遇到了一个非常奇怪的问题,完成块被连续调用了两次。KVO调用看起来不错,但completionBlock仍然奇怪地被调用了两次。我是不是误解了手术?文档中说,当
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");
}
当它完成时,调用这个方法(只调用了一次,我仔细检查了一下)

但是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
,因此这可能不是原因


我真的不明白为什么completionBlock被调用了两次。即使在完成块内部将完成块设置为nil时,有时也会调用两次,这更奇怪。

不确定这是否是原因,但根据我的经验,没有必要重写只读状态属性。您负责定期检查主循环中的isCancelled,以及它是否设置为退出您正在执行的任何操作,但我相信其他状态标志(isReady、isFinished、isExecuting)会自动处理

如果您去掉状态标志处理,只在
-main
中执行流程,它会触发多少次

编辑:假设您正在覆盖这些标志以允许并发,那么您应该通读注释


从外观上看,您不需要覆盖
isReady
isCancelled
,而是根据文档中的说明覆盖
-start

是的,您是对的!我以前一定是看错文件了。我现在在-start中启动一个自定义后台线程,我已经删除了isReady和isCancelled覆盖,现在它可以工作了,完成块只调用一次:)我同意您不想实现自己的
isReady
isCancelled
方法。如果您确实需要定制
isReady
,您必须调用
super
:正如文档所说,“如果要使用自定义条件确定操作对象的就绪状态,可以重写此方法并返回一个准确反映接收器就绪状态的值。如果这样做,您的自定义实现应该调用super并将其返回值合并到对象的就绪状态中。您的自定义实现还必须为isReady密钥路径生成适当的KVO通知。”
- (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;
}