我可以用addOperationWithBlock取消添加到NSOperationQueue的Block吗?

我读了许多文章说“块是未来!!!”。 我想知道它是否涉及到在后台运行操作。

例如,我有一个表格视图,其中有来自networking的图像。 现在我可以使用+[NSOperationQueue addOperationWithBlock:]来获取它们。 当单元格变为可见时,会将操作发送到队列。 但有一种方法可以取消它,一旦细胞滚动屏幕? 或者是唯一的方法来做到NSOperation子类? 使用块很容易,所以我只是在我试图解决这个 NSOperation子类的例子之前问这个问题…

问题似乎是你是否可以创build一个可取消的NSBlockOperation 。 正如这个答案所build议的,从WWDC 2012会议#211build立并行用户界面引用,你当然可以。

尽pipe如此,这种方法还是有限制的。 值得注意的是,你必须把取消逻辑放在你的块中。 这工作正常,如果您的块正在运行一个循环,它可以重复检查isCancelled状态。 但是,如果您处于某个networking请求的中间,则在NSBlockOperation执行操作将会很尴尬。

使用其他答案(以及WWDC 2012video)中列出的模式,您可以编写一个NSBlockOperation ,它使用基于块的NSURLSession和轮询循环的折磨组合,如果取消操作,则取消NSURLSessionTask ,从而完成您的任务,但这是一个可怕的解决scheme(效率低下,麻烦,阻碍你的应用程序代码与块中的取消逻辑等)。

如果你想做一个可取消的networking操作,一个NSOperation子类将是一个更好的方法来做到这一点。 你第一次这样做,看起来很麻烦,但是一旦你熟悉了这个模式,实现就变成了第二个本质和微不足道的东西。 你会发现自己一次又一次地回到这种模式。 请参阅“ 并发编程指南”的“ 操作队列”一章的“ 定义自定义操作对象”部分,了解有关进行可取消并发操作的讨论,特别是关于“响应取消事件”的讨论。

作为最后的观察,你描述了这个“使用块”和NSOperation subub作为“任一/或”命题。 然而,实际上,你经常结婚的两种技术,创build一个NSOperation子类,它采取块参数,指定下载完成后你想要做什么。 请参阅AFNetworking作为如何结婚块和NSOperation子类的一个很好的例子。

在附注中,签出WWDC 2015会话,这是如何在项目中使用NSOperations的一个很好的例子:

https://developer.apple.com/videos/wwdc/2015/?id=226

关于您的可取消块,您应该签出ReactiveCocoa 。 对我来说这是一个完美的解决scheme,因为你可以取消networking请求的信号: https : //github.com/ReactiveCocoa/ReactiveCocoa

我也用它来创build可取消的延迟块。 你可以在这里阅读更多关于它的信息: http : //www.avanderlee.com/2015/07/25/cancellable-delayed-blocks/

基于@安托万的想法

- (void(^)())executeSomeBlock:(void(^)())someBlock { __block volatile int32_t isCancelled = 0; [self.someOperationQueue addOperationWithBlock:^(){ if (!isCancelled) { someBlock(); } }]; return ^(){OSAtomicCompareAndSwap32Barrier(0, 1, &isCancelled);}; }

用法:

void (^cancelMe)() = [self executeSomeBlock:myBlock];

如果你想取消该块:

cancelMe();

永远不要testing它。 随意尝试一下。

我想可以把这个想法包装到NSOperation的类别中。

***由@ CouchDeveloper的build议更新

你可以这样做

 NSOperationQueue *opQueue = [[NSOperationQueue alloc] init]; //... NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ }]; [opQueue addOperation:operation]; //... [operation cancel];