NSOperation работает, но отсутствует в NSOperationQueue - PullRequest
0 голосов
/ 16 марта 2012

Недавно я отлаживал проблему с зомби с помощью операций и обнаружил, что вызов метода cancelAllOperations в очереди не отменяет данную операцию, и на самом деле очередь операций пуста, хотя операция все еще выполняется. *

Структура представляла собой 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, вызывая init и viewDidAppear, начиная операцию.
    • [Операции mOperationQueue] содержит ровно один элемент;
  • Вскоре после этого операция входит в основной и
  • Пользователь покидает viewcontroller до завершения операции.
  • dealloc вызывается в viewcontroller (поскольку операция сохраняет слабую ссылку)
    • [Операции mOperationQueue] содержат ноль (!) Элементов
  • cancelAllOperations отправляется в очередь операций
    • [Отмена NSOperation] не вызывается, в результате чего отображается поддельное состояние, видимое приложению.
  • dealloc заканчивает
  • операция завершена
    • isCancelled возвращает false, что приводит к вызову зомби

Документация NSOperationQueue, однако, прямо заявляет, что «Операции остаются в очереди, пока они не завершат свою задачу». что выглядит как нарушение договора.

Я исправил сбой, сохранив ссылку на операцию и вручную отправив отмену, но я хотел бы знать, почему оригинальный подход не работает для предотвращения дальнейших проблем. Может кто-нибудь пролить свет на это?

Заранее спасибо.

1 Ответ

0 голосов
/ 16 марта 2012

cancelAllOperations не отменяет уже запущенную операцию.Он только сообщает операции об этом факте и позволяет операции отменить себя, , когда захочет .Таким образом, вы можете получить условие повышения.Перейдите к deallocacion, после , вы уверены, что операция отменена.

...