Я работаю над подклассом NSOperation, и я столкнулся с этой очень странной проблемой, так как блок завершения вызывается дважды подряд. Навыки KVO кажутся прекрасными, но завершение Блока все еще странно называется дважды. Неужели я не понимаю NSOperation? В документации сказано, что блок завершения вызывается, когда isFinished
становится YES
и что происходит только один раз в моем коде:NSOperation completeBlock вызывается дважды
- (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
в моем коде тестирования, так что не может быть причиной.
Я действительно не понимаю, почему ComplelockBlock вызывается дважды. Даже при установке блока завершения в ноль из блока завершения его иногда называют дважды, что еще более странно.
Да, вы правы! Раньше я неправильно читал документы. Теперь я запускаю пользовательский фоновый поток в -start, и я удаляю переопределение isReady и isCancelled, и теперь он работает, блок завершения вызывается только один раз :) – JonasG
Я согласен, что вы не хотите реализовывать свой собственный 'isReady 'или' isCancelled'. Если вам нужен пользовательский 'isReady', вам нужно вызвать' super': Как говорят документы: «Если вы хотите использовать пользовательские условия для определения готовности вашего рабочего объекта, вы можете переопределить этот метод и вернуть значение, которое точно отражает готовность приемника.Если вы это сделаете, ваша пользовательская реализация должна вызывать супер и включать ее возвращаемое значение в состояние готовности объекта. Ваша пользовательская реализация также должна генерировать соответствующие уведомления KVO для пути ключа isReady ». – Rob