如何使用调度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

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

从上面的代码我有两个问题我不能解决。

  1. 我如何使它使我的弱引用在dispatch_after块中不被释放?把它放在那里的目的是让应用暂停3秒。如果dispatch_after是不正确的,那么我在那里使用什么代码来防止它变成nil?

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

dispatch_after调度块并立即返回。因此,您的NSBlockOperation的executionBlock几乎没有工作要做——它立即完成并从队列中删除。此时,该操作被释放,因此在稍后调用dispatch_after块之前,弱引用变为nil。

如果您先执行dispatch_after并从该块内部调度操作,那么它可能适合您的需要。您可以使用sleep,但我不建议这样做,因为您将不必要地阻塞线程。关于NSOperation和delay的更多讨论请参见这个问题

您可以在dispatch_after块内调度操作,并将aBlockOperation声明为实例变量/属性,因此aWeakBlockOperation不会变为nil。

但是你不需要纠结于NSBlockOperation来实现你的目标。您可以使用dispatch_block_t实例变量,每次单击列时将其设置为一个新值(在单击列后需要执行的代码块):

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

相关内容

  • 没有找到相关文章

最新更新