【问题标题】:NsoperationQueue Cancel all operations is not cancelled until it finishes the operationNsoperationQueue 取消所有操作直到完成操作才取消
【发布时间】:2015-11-23 19:37:12
【问题描述】:

在我看来,我有图像视图,图像视图的数据来自 Url,图像大约 1-3 MB。 如果用户滑动然后我想加载下一张图片,如果慢慢滑动,一切都很好,但是当我快速滑动时,我想取消之前的操作并从新的 url 开始。

例如。如果第二张和第三张图片的操作在中间,用户滑动 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 


         }];

     }];
 }

谢谢。

【问题讨论】:

  • 请努力格式化您的代码,以便其他人可以阅读。
  • 您是否在每次需要加载图像时都重新创建BackgroundOperation(使用BackgroundOperation=[[NSOperationQueue alloc]init];)?

标签: ios nsoperationqueue cancellation


【解决方案1】:

NSOperationQueue 上调用cancelAllOperations 只会在其每个操作上调用cancel。如果NSOperation 没有覆盖cancel,那么它永远不会被取消。

NSBlockOperation 启动后没有取消它的概念。该块只需执行即可。

如果您想指定特殊的取消行为(例如取消图片下载),您需要继承 NSOperation 并覆盖 cancel

AFNetworkingSDWebImage 中有很多这样的例子

要取消图像下载,您需要将NSURLSesionDownloadTask 包裹在NSOperation 中,然后覆盖cancel 以在NSURLSesionDownloadTask 上调用cancel

【讨论】:

  • 无需子类化 NSOperation 即可取消,可以在执行的块内完成
  • 这将取消阻止,但是一旦图像下载开始,只需使用 dataWithContentsOfURL 就无法停止它
  • cancel 实际上并没有在所有操作上调用,它只是将 isCancelled 设置为 YES
【解决方案2】:

取消操作只是将其 isCancelled 标志设置为 true。

您有责任检查您的操作是否已被取消,在它开始运行之前(或者在它运行期间,如果它是一个长时间运行的操作)。

您可以check if your operation is cancelled within an operation block,但我建议使用子类,而不是使用块。

【讨论】:

  • 我没看清楚,看来v必须检查isCancelled。但我很困惑在我的代码中哪里检查它
  • 我没有使用 Nsoperation,似乎 isCancelled 存在于 nsoperation
  • NSBlockOperationNSOperation 的子类。可以取消。再次检查链接并查看它如何捕获(弱)块操作,因此可以在块内检查 isCancelled。如果您仍然不确定如何执行此操作,check this detailed article 也会取消块操作。
  • 我会尝试使用这个链接,但我没有使用 ARC,所以 __weak NSBlockOperation *weakOperation = loadImageOperation;
  • 您应该使用 ARC。你为什么不呢?
【解决方案3】:

取消操作只会将其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..
];

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-16
    • 2012-09-21
    • 1970-01-01
    相关资源
    最近更新 更多