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

时间:2014-06-06 17:05:36

标签: ios cocoa-touch objective-c-blocks nsoperation nsoperationqueue

我读了许多文章,说'" BLOCKS是未来!!!"。我想知道它是否与在后台运行操作有关。

例如,我有一个表格视图,其中包含来自网络的图像。现在我可以使用+[NSOperationQueue addOperationWithBlock:]来获取它们。当单元格变为可见时,操作将被发送到队列。但是有一种方法可以在单元格从屏幕滚动后取消它吗?或者是继承NSOperation的唯一方法吗?使用块非常简单,所以在我尝试解决NSOperation子类的this example之前,我只是问这个问题...

4 个答案:

答案 0 :(得分:11)

问题似乎在于您是否可以创建可取消的NSBlockOperation。如this answer所示,引用WWDC 2012 session #211, Building Concurrent User Interfaces,你当然可以。

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

使用其他答案(以及WWDC 2012视频)中列出的模式,您可以编写一个NSBlockOperation,它使用了基于块的NSURLSession的折磨组合和取消{{0}}的轮询循环{1}}如果操作被取消,它会完成你想要的操作,但这是一个非常糟糕的解决方案(效率低下,繁琐,使用块中的取消逻辑来阻止您的应用程序代码等)。

如果要进行可取消的网络操作,NSURLSessionTask子类将是一种更优雅的方法。第一次这样做,它看起来很麻烦,但是一旦你熟悉了这个模式,它就变成了第二个本质而且很容易实现。你会发现自己一次又一次地回到这种模式。有关进行可取消的并发操作的讨论,请参阅并发编程指南操作队列章节的Defining a Custom Operation Object部分,特别是关于“响应取消事件”的讨论”。

作为最后的观察,你将这个“使用块”和NSOperation - 子类描述为“或/或”命题。但是,实际上,您实际上要将这两种技术结合起来,创建一个NSOperation子类,该子类采用块参数来指定下载完成后要执行的操作。请参阅AFNetworking,作为如何结合块和NSOperation子类的一个很好的例子。

答案 1 :(得分:1)

在旁注中,查看WWDC 2015会话,它是如何在项目中使用NSOperations的一个很好的例子:

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

关于您的可取消区块,您应该结帐ReactiveCocoa。对我而言,它是一个完美的解决方案,因为您可以取消网络请求的信号: https://github.com/ReactiveCocoa/ReactiveCocoa

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

答案 2 :(得分:0)

基于@Antoine的想法

- (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();

永远不要测试它。随意尝试。

我想可以将这个想法包装成NSOperation的类别。

***由@ CouchDeveloper的建议更新

答案 3 :(得分:-3)

你可以这样做

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

}];
[opQueue addOperation:operation];
//...
[operation cancel];