我遇到了这个奇怪的错误..基本上我得到了这个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
});
};
答案 0 :(得分:2)
UIKit不是线程安全的。 taskQ
不是主队列,因此命令A将在不是主队列的全局队列上执行。
考虑将主队列分配给taskQ
,或者让命令A在主队列上的distpatch_async
上执行。