I'm running into this weird bug.. basically I got this blocK definition:
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
});
};
this block is called from the worker queue like so:
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);
(I know you'll ask: why the delegate? don't worry it just saves me a lot of trouble, and I believe it's irrelevant to this discussion).
The thing I noticed is that this command A
only executes after command B
is done.. the idea was to update the UI with some information for the user.. then dismiss the UI holding that label after 1 second (I wanted to give the user enough time to read the notification.. know what's going on.. then have the UI dismiss itself).
what's happening is that command A
executes and the UI dismisses at the same time! if I take the whole dispatch after clause out.. command A
executes as desired and that's it.
I also tried doing this:
__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
});
};
I also tried changing the queue from dispatch_get_main_queue()
to dispatch_get_global_queue()
and vice versa.. still no luck..
ideas?
update (with correct answer)
based on Mohannad's answer below.. this is what my final solution looks like (note: it turns out that both command A and command B involves UI changes.. so both should be done on the main queue.. the interesting part is that the the whole block was placed on a global queue.. which gave increased the delay in their execution, I also took out the delegate as it wasn't necessary)
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
});
};