如何使用调度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个问题,我无法解决。
-
我如何做到这一点,使我的弱引用不释放dispatch_after块? 把它放在那里的目标是暂停应用程序正好3秒。 如果dispatch_after不正确,那么我使用哪些代码来防止它成为零?
-
为什么我调用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(); }); }