我可以用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];