NsoperationQueue Отмена всех операций не отменяется до завершения операции

На мой взгляд, у меня есть представление изображения, данные для просмотра изображения поступают из URL-адреса, изображения составляют около 1-3 МБ. Если пользователь прокручивает, я хочу загрузить следующее изображение. Все работает нормально, если прокручивать медленно, но когда я прокручивал быстро, я хочу отменить предыдущую операцию и начать с нового URL-адреса.

Для экс. если пользователь проводит 4 раза, если операции для 2-го и 3-го изображений находятся посередине, я хочу отменить их и начать загрузку 4-го изображения

Но теперь вместо 4-го изображения я получаю первое 2-е изображение, за которым следует 3-е, а затем появляется 4-е изображение.

Вот мой пример кода

- (void)handleSwipeLeft:(UISwipeGestureRecognizer *)aSwipeGestureRecognizer {


    [BackgroundOperation cancelAllOperations];  // To cancel previous one 


    [self performSelector:@selector(LoadImage) withObject:nil afterDelay:0.1];


}

-(void)LoadImage
{
    BackgroundOperation=[[NSOperationQueue alloc]init];  


    imgvww.image=[UIImage imageNamed:@"loader.png"]; // Place holder    till download finishes 


   [BackgroundOperation addOperationWithBlock:^
     {
         UIImage *img=[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[[self.ItemDetails objectAtIndex:0] objectForKey:@"ImageUrl"]]]];  // Getting data from URL 

         [[NSOperationQueue mainQueue] addOperationWithBlock:^{


             imgvww.image=img;  //Adding to image view after completion 


         }];

     }];
 }

Спасибо.


person siva krishna    schedule 29.08.2015    source источник
comment
Пожалуйста, постарайтесь отформатировать свой код так, чтобы другие люди могли его прочитать.   -  person jtbandes    schedule 29.08.2015
comment
Вы воссоздаете BackgroundOperation каждый раз, когда нужно загрузить изображение (с BackgroundOperation=[[NSOperationQueue alloc]init];)?   -  person Khanh Nguyen    schedule 29.08.2015


Ответы (3)


Отмена операции просто устанавливает флаг isCancelled в значение true.

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

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

person Community    schedule 29.08.2015
comment
Я не совсем понял, кажется, нужно проверить isCancelled. Но я запутался, где это проверить в моем коде. - person siva krishna; 29.08.2015
comment
Я не использую Nsoperation, кажется, isCancelled существует для nsoperation - person siva krishna; 29.08.2015
comment
NSBlockOperation является подклассом NSOperation. Его можно отменить. Снова проверьте ссылку и посмотрите, как она захватывает (слабую) блоковую операцию, чтобы можно было проверить isCancelled внутри блока. Если вы все еще не знаете, как это сделать, ознакомьтесь с подробной статьей, которая также отменяет операции блокировки. - person ; 29.08.2015
comment
K я попробую с этой ссылкой, но я не использую ARC, поэтому какая альтернатива для __weak NSBlockOperation *weakOperation = loadImageOperation; - person siva krishna; 29.08.2015
comment
Замените __weak на __block. - person ; 29.08.2015
comment
вы должны использовать ARC. почему бы и нет? - person Yariv Nissim; 29.08.2015
comment
@ yar1vn V запустил проект без ARC, когда v r поддерживает более ранние версии. Но v r работает над этим, чтобы поддержать ARC - person siva krishna; 29.08.2015
comment
@PetahChristian Есть ли способ приостановить и возобновить операцию? - person siva krishna; 29.08.2015
comment
@siva вы можете приостановить очередь, но уже запущенные операции не будут приостановлены. Если вам нужен более сложный контроль над загрузкой, вам нужно использовать другой подход, подобный тому, что предложил DBoyer. - person ; 29.08.2015
comment
@PetahChristian Я пройду через это, спасибо за информацию - person siva krishna; 29.08.2015
comment
@siva Не забудьте проголосовать за другие ответы. Вы получили хорошую помощь от нескольких человек! - person ; 29.08.2015

Вызов cancelAllOperations для NSOperationQueue будет просто вызывать cancel для каждой из его операций. Если NSOperation не перекрывает cancel, то его никогда не отменят.

Нет концепции отмены NSBlockOperation после того, как она началась. Блок просто выполняется и все.

Если вы хотите указать особое поведение при отмене (например, отмену загрузки изображения), вам необходимо создать подкласс NSOperation и переопределить cancel.

Есть много примеров этого в AFNetworking или SDWebImage

Чтобы отменить загрузку изображения, вам нужно заключить NSURLSesionDownloadTask в NSOperation, а затем переопределить cancel, чтобы вызвать cancel на NSURLSesionDownloadTask.

person DBoyer    schedule 29.08.2015
comment
нет необходимости создавать подкласс NSOperation, чтобы иметь возможность отменить, это можно сделать в рамках выполняемого блока - person Yariv Nissim; 29.08.2015
comment
Это отменит блокировку да, но как только загрузка изображения начнется, ее нельзя будет остановить, просто используя dataWithContentsOfURL - person DBoyer; 29.08.2015
comment
cancel на самом деле не вызывается для всех операций, он просто устанавливает isCancelled в YES - person trapper; 15.02.2017

Отмена операции только изменит его свойство isCancelled на YES.
Чтобы иметь возможность отменить операцию, вы должны сделать следующее:

NSBlockOperation * op = [NSBlockOperation new];
__weak NSBlockOperation * weakOp = op; // Use a weak reference to avoid a retain cycle
[op addExecutionBlock:^{
    // Put this code between whenever you want to allow an operation to cancel
    // For example: Inside a loop, before a large calculation, before saving/updating data or UI, etc.
    if (weakOp.isCancelled) return;

    // Do something..
];
person Yariv Nissim    schedule 29.08.2015