如何使用调度gcd与NSOperationQueue和NSBlockOperation?

这是代码

@interface ViewController () @property (nonatomic, strong) NSOperationQueue *queue; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; _queue = [[NSOperationQueue alloc] init]; NSBlockOperation *aBlockOperation = [[NSBlockOperation alloc] init]; __weak NSBlockOperation* aWeakBlockOperation = aBlockOperation; [aBlockOperation addExecutionBlock:^{ NSLog(@"queue should still have the operation. And it does. yay!: %@", [_queue operations]); // This should print correctly. It will show the NSBlock operation correctly residing inside the NSOperationQueue dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"Now queue is empty??: %@", [_queue operations]); // This should print as being empty NSLog(@"And a weak block is nil???: %@", aWeakBlockOperation); // This should print out **nil** if (![aWeakBlockOperation isCancelled]) { // Now i have no way to check the operation } }); }]; [_queue addOperation:aBlockOperation]; @end 

[ 编辑 ]目标是有这样的用户交互:有5个或更多的单元格在屏幕上的tableView。 当用户点击一个单元格时,后台进程将执行后台进程,这将需要一段时间。 该应用程序将以3秒为间隔检查用户是否点击了另一个单元格。 如果用户点击另一个单元格,我应该从队列中取消当前操作,并开始处理用户点击的新单元格。

从上面的代码我有2个问题,我无法解决。

  1. 我如何做到这一点,使我的弱引用不释放dispatch_after块? 把它放在那里的目标是暂停应用程序正好3秒。 如果dispatch_after不正确,那么我使用哪些代码来防止它成为零?

  2. 为什么我调用dispatch_after后,我的NSOperationQueue变空了? 有没有办法让它变成空的?

dispatch_after安排块并立即返回。 所以,你的NSBlockOperation的executionBlock几乎没有工作要做 – 它立即完成并从队列中删除。 此时,操作被释放,因此在稍后调用dispatch_after块之前弱参考变为零。

如果先执行dispatch_after并从该块内部安排操作,则可能适合您的需要。 你可以使用sleep ,但我不会build议,因为你会不必要地阻塞线程。 看到这个问题更多关于NSOperation和延迟的讨论。

您可以在dispatch_after块内调度操作,并将aBlockOperation声明为实例variables/属性,这样aWeakBlockOperation不会变为零。

但是你不需要为了实现你的目标而烦恼NSBlockOperation。 您可以使用dispatch_block_t实例variables,每次点击该列时,您将设置一个新值(在单击该列后需要执行代码的块):

 @implementation ViewController { dispatch_block_t columnBlock; } - (void)columnClicked { columnBlock = ^{ ... your code ... }; __weak dispatch_block_t weakColumnBlock = columnBlock; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ dispatch_block_t colBlock = weakColumnBlock; if (colBlock) colBlock(); }); }