Я недавно отлаживал проблему с зомби с операциями и выяснил, что вызов cancelAllOperations в очереди не отменяет эту операцию, и на самом деле очередь операций была пуста, хотя операция все еще бежал.NSOperation работает, но отсутствует в NSOperationQueue
Структура была viewcontroller, которая асинхронно загружала набор изображений из Интернета и выполняла некоторые изменения на них. Соответствующие (анонимные) их фрагменты следуют:
@implementation MyViewController
- (id) init
{
(...)
mOperationQueue = [[NSOperationQueue alloc] init];
(...)
}
- (void) viewDidAppear:(BOOL)animated
{
(...)
MyNSOperation * operation = [[MyNSOperation alloc] initWithDelegate:self andData:data];
[mOperationQueue addOperation:operation];
[operation release];
(...)
}
- (void) dealloc
{
(...)
[mOperationQueue cancelAllOperations];
[mOperationQueue release];
(...)
}
- (void) imagesLoaded:(NSArray *)images
{
(...)
}
И данная операция:
@implementation MyNSOperation
- (id) initWithDelegate:(id)delegate andData:(NSDictionary *)data
{
self = [super init];
if (self)
{
mDelegate = delegate; // weak reference
mData = [data retain];
(...)
}
return self;
}
- (void) main
{
NSAutoReleasePool * pool = [[NSAutoReleasePool alloc] init];
mImages = [[NSMutableArray alloc] init];
// load and compose images
mAlteredImages = (...)
[self performSelectorOnMainThread:@selector(operationCompleted) withObject:nil waitUntilDone:YES];
[pool release];
}
- (void)operationCompleted
{
if (![self isCancelled])
{
[mDelegate imagesLoaded:mAlteredImages];
}
}
Наблюдаемый поток следующим образом:
- ViewController показан, призывающие инициализации и viewDidAppear запуска операция.
- [операции mOperationQueue] содержит ровно один элемент;
- Вскоре после того, операция переходит в основной и
- ViewController происходит выход пользователя до завершения операции.
- dealloc называется на ViewController (поскольку операция сохраняет слабую ссылку)
- [mOperationQueue операций] содержит ноль (!) Элементы
- cancelAllOperations отправляется в очередь операции
- [ NSOperation cancel] не вызывается, в результате появляется видимое фиктивное состояние приложения.
- dealloc заканчивает
- операция завершается
- isCancelled возвращает ложь, в результате зомби вызова
Документация NSOperationQueue однако четко указано, что «операции не остаются в очереди, пока они закончить свою задачу ». который выглядит как нарушение контракта.
Я исправил сбой, сохранив ссылку на операцию и вручную отменив отмену, но я хотел бы знать, почему оригинальный подход не работает для предотвращения дальнейших проблем. Может кто-то пролить свет на это?
Заранее спасибо.
@Combuster ... вы можете поделиться своим рабочим кодом для своего вопроса здесь – Priya