I have seen the following used:
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
//code to be executed on the main queue after delay
[self doSometingWithObject:obj1 andAnotherObject:obj2];
});
But shouldn't it use weak self in the block?
__weak typeof(self) weakSelf = self;
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
//code to be executed on the main queue after delay
[weakSelf doSometingWithObject:obj1 andAnotherObject:obj2];
});
I'm newish to GCD and Blocks and trying to work out the most correct usage. Many thanks on any guidance on this one.
It depends upon the desired behavior.
The first syntax (referring to self
in the block) will maintain a strong reference to the view controller until the dispatch_after
fires and doSometingWithObject
successfully run. This will happen even if the view associated with that view controller is dismissed in the intervening period.
So, you'd use this pattern only in cases where you absolutely need that method to run, even after the view associated with that view controller was dismissed. For example, if that method is updating some model objects, saving something to persistent storage, posting some network request, etc.
The second syntax (the weakSelf
pattern), will not maintain a strong reference to the view controller, and thus if the view associated with the view controller was dismissed by the time the block runs, the view controller will be released and weakSelf
will be nil
, and thus doSometingWithObject
will not be called. (Obviously, if the view has not yet been dismissed, the view controller will not have been released, weakSelf
will not be nil
and that method will be called.)
You will do that if the method in question only needs to be called if the view has not yet been dismissed. For example, if the sole purpose of the method is to update some UI object on that view, you obviously don't need to do call that method if the view has been dismissed already. And in that scenario, you'd generally prefer the use weakSelf
so that the view controller is promptly released when it is no longer needed.
Just for the sake of completeness, there is actually a third permutation of this pattern, sometimes (jokingly) called the weakSelf
/strongSelf
"dance":
__weak typeof(self) weakSelf = self;
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
//code to be executed on the main queue after delay
typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf doSomethingWithObject:obj1 andAnotherObject:obj2];
[strongSelf doSomethingElseWithObject:obj1];
}
});
This pattern is very similar to the second example, where the method(s) are not called if self
is deallocated. You use this pattern when you want a weak reference, but either (a) you need to ensure that it isn't deallocated while the block is running; or (b) when you need to test to see if it is nil
or not, but want avoid race conditions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With