我读了许多文章,说'" BLOCKS是未来!!!"。我想知道它是否与在后台运行操作有关。
例如,我有一个表格视图,其中包含来自网络的图像。现在我可以使用+[NSOperationQueue addOperationWithBlock:]
来获取它们。当单元格变为可见时,操作将被发送到队列。但是有一种方法可以在单元格从屏幕滚动后取消它吗?或者是继承NSOperation
的唯一方法吗?使用块非常简单,所以在我尝试解决NSOperation
子类的this example之前,我只是问这个问题...
答案 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];