Проблемы с вызовом NSOperationQueue и Dealloc и сбоем приложения

Я создал NSOperation в очереди следующим образом:

ImageLoadingOperation *operation = [[ImageLoadingOperation alloc] initWithImageURL:url target:self action:@selector(didFinishLoadingImageWithResult:)];
[operationQueue addOperation:operation];
[operation release];

И это отлично работает, но если представление открывается до завершения операции, приложение вылетает с ошибкой «EXC_BAD_ACCESS».

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

Любые идеи?


person Rudiger    schedule 03.09.2010    source источник
comment
Итак, OperationQueue принадлежит представлению, и очередь освобождается вместе с представлением?   -  person Graham Perks    schedule 03.09.2010
comment
Я пытался остановить очередь операций до того, как очередь и представление будут освобождены, но безуспешно.   -  person Rudiger    schedule 03.09.2010


Ответы (3)


Это общая проблема для View, вызывающего некоторую сеть, а затем обратного вызова.

Мое решение заключается в том, что вы можете сохранить представление до вызова операции. И затем, когда операция завершается, вы освобождаете представление.

- (void)longTask {
   [self retain];
}

- (void)longTaskDidFinish {
   // do something if you want
   [self release];
}
person vodkhang    schedule 03.09.2010

Вам придется либо переопределить операцию «отменить» в вашем классе ImageLoadingOperation, либо добавить себя в качестве наблюдателя KVO к свойству «отменено». Там - вы можете разумно отменить свою операцию таким образом, чтобы она не рухнула.

Кроме того, если ваша операция ImageLoadingOperation выполняется в фоновом режиме, было бы разумнее как-то отложить ваш доступ к представлениям в основной поток (где происходит все рисование). Вы можете использовать dispatch_sync(dispatch_get_main_queue(), ^{}); или даже выполнить SelectorOnMainThread для фактического доступа к соответствующему представлению.

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

person Motti Shneor    schedule 24.10.2015

Вы можете сохранить представление до того, как будет вызван обратный вызов операции, как упоминалось выше vodkhang. Но это излишне продлит жизнь представления, потому что, поскольку представление извлечено, вы не хотите, чтобы операция продолжалась дальше.
Вот набросок того, что вы должны сделать, чтобы отреагировать на команду отмены:

- (void)start{
    if(self.isCancelled){
       [self markAsFinished];
       return;
    }
    //start your task asynchronously
}


//If you want to cancel the downloading progress immediately, implement your own 'cancel' method
- (void)cancel{
    [super cancel];
    if(self.isExecuting){
       {
          ......
          cancel load process
          ......
       }
       [self markAsFinished];
    }
}

- (void)markAsFinished{
    ......
    change 'finished' to YES'  generate KVO notifications on this key path
    change 'executing' to 'YES'; generate KVO notification on this key path
    ...... 
}

Этот скетч основан на сетевой библиотеке ASIHTTPRequest и содержит официальное руководство о том, как реагировать на команду отмены.

person Mindy    schedule 16.11.2015