如何使块立即执行代码并在延迟之后执行代码

时间:2013-05-22 10:18:44

标签: ios objective-c delegates grand-central-dispatch

我遇到了这个奇怪的错误..基本上我得到了这个blocK定义:

UILabel* filterButtonLabel;
void (^labelUpdater)(NSString *, id) = ^(NSString* newLabelText, id delegate){
    filterButtonLabel.text = newLabelText;   // command A   
    dispatch_after(DISPATCH_SECONDS_FROM_NOW(1), dispatch_get_main_queue(), ^{
        [delegate abortFilter];  //command B
    });
};

从工作队列中调用此块,如下所示:

dispatch_queue_t taskQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(taskQ, ^{
    [searchWorker withDelegate:self withUpdater:labelUpdater]; //<- worker thread in here
});

updater(@"filter applied", delegate);

(我知道你会问:为什么代表?不要担心它只会给我带来很多麻烦,我相信这与这次讨论无关)。

我注意到的事情是这个command A仅在command B完成后执行..这个想法是用用户的一些信息更新UI ..然后解除持有该标签的UI 1秒(我想给用户足够的时间来阅读通知..知道发生了什么......然后让UI解雇自己。)

正在发生的事情是command A执行并且UI同时解散!如果我把整个派遣后的条款拿出来...... command A按照需要执行,就是这样。

我也试过这样做:

__block UILabel* filterButtonLabel;
void (^labelUpdater)(NSString *, id) = ^(NSString* newLabelText, id delegate){
    filterButtonLabel.text = newLabelText;   // command A   
    dispatch_after(DISPATCH_SECONDS_FROM_NOW(1), dispatch_get_main_queue(), ^{
        [delegate abortFilter];  //command B
    });
};

我也尝试将队列从dispatch_get_main_queue()更改为dispatch_get_global_queue(),反之亦然..仍然没有运气..

想法?


更新(正确答案)

基于下面的Mohannad answer ..这是我的最终解决方案的样子(注意:事实证明命令A和命令B都涉及UI更改..所以两者都应该在主队列上完成。有趣的是,整个块被放置在一个全局队列中..这增加了执行的延迟,我也拿出了代表,因为没有必要)

void (^labelUpdater)(NSString *, id) = ^(NSString* newLabelText){
    dispatch_async(dispatch_get_main_queue(), ^ {
        filterButtonLabel.text = newLabelText;   // command A -> includes a UI change
    });

    dispatch_after(DISPATCH_SECONDS_FROM_NOW(2), dispatch_get_main_queue(), ^{
        [self abortFilter];  //command B -> also includes a UI change
    });
};

1 个答案:

答案 0 :(得分:2)

UIKit不是线程安全的。 taskQ不是主队列,因此命令A将在不是主队列的全局队列上执行。

考虑将主队列分配给taskQ,或者让命令A在主队列上的distpatch_async上执行。