Операция завершения NBlock вызывается дважды
Я работаю над подклассом NSOperation, и я столкнулся с этой очень странной проблемой, когда блок завершения вызывается дважды подряд. Вызовы KVO кажутся нормальными, но блок завершения все еще странно вызывается дважды. Я неправильно понимаю 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");
}
Когда он заканчивается, вызывается этот метод (он вызывается только ОДИН РАЗ, я дважды проверил это)
- (void)completeOperation {
[self willChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];
executing = NO;
completed = YES;
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];
}
Но блок завершения вызывается дважды и дважды печатает "Завершено" в консоли.
А вот методы, которые указывают текущее состояние:
- (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
в моем тестовом коде, так что это не может быть причиной этого.
Я действительно не понимаю, почему блок завершения вызывается дважды. Даже при установке блока завершения на ноль из блока завершения он иногда вызывается дважды, что даже страннее.
1 ответ
Не уверен, что это причина, но по моему опыту, нет необходимости переопределять свойства состояния только для чтения. Вы несете ответственность за периодическую проверку isCancelled в основном цикле, и если он настроен на выход из того, что вы делаете, но я считаю, что другие флаги состояния (isReady, isFinished, isExecuting) позаботятся автоматически.
Сколько раз он срабатывает, если вы уберете обработку государственного флага и просто выполните свой процесс в -main
?
РЕДАКТИРОВАТЬ: Предполагая, что вы переопределяете эти флаги для обеспечения параллелизма, тогда вы должны прочитать примечания в документации
Судя по всему, вы никогда не должны переопределять isReady
или же isCancelled
и вместо этого переопределить -start
в соответствии с инструкциями в документе.