1

I'm working on a project where I see a lot of code that uses completion blocks with __strong references for a __weak variable to perform operations on that object in the completion block. We want to avoid an EXEC_BAD_ACCESS crash if the completion block fires after the view is deallocated, and also not retain the view controller until the completion block finishes. Here's some sample pseudo code:

__weak UIViewController *weakSelf = self;
[[DataManager sharedInstance] dataWithCompletionBlock:^(id data) {
    if (!weakSelf) return;
    __strong UIViewController *strongSelf = weakSelf;
    strongSelf.data = data;
}];

The way I understand memory management, weakSelf, if it passes the conditional check, will not be deallocated until the end of the run loop at the earliest, so the __strong reference is unnecessary. Instead, the __weak reference can be safely acted on since there is a conditional already checking for it to prevent a EXEC_BAD_ACCESS crash. A __strong reference should only be necessary if we had something like calling an async method with its own completion block that needed the view controller not to be deallocated.

What is the proper usage here? Is __strong necessary? or is it safe to simply access the __weak variable? Am I correct in my understanding of how this works?

jscs
  • 63,694
  • 13
  • 151
  • 195
gdavis
  • 2,556
  • 1
  • 20
  • 25
  • It's actually the `if( !weakSelf )` that's unnecessary, although it does helpfully make explicit that nothing will happen in that case. The strong reference is necessary to keep the reference alive as long as the Block is _running_. – jscs Oct 02 '14 at 02:52
  • I think CodaFi's answer on this other question answers yours, but if it's still unclear, feel free to edit your question and ping me. – jscs Oct 02 '14 at 02:54
  • Note that most cases where people use a weak reference to self you do not actually need to use a weak reference. Some people like to just use weak everywhere to avoid having to think about retain cycles. Only certain block use cases will cause a retain cycle, most of the time it's fine to just refer to self (which will be strong as all block variables are by default). So, basically, the answer is "it depends" and the weak/strong pattern you've shown here is only needed in some cases. But there's nothing wrong with doing it everywhere just in case. – Abhi Beckert Oct 02 '14 at 06:24
  • Also note that `weakSelf` will be set to `nil` if `self` goes away. A lot of obj-c code can execute perfectly fine if a variable is `nil`. In the code provided in this question, there is no reason to check for `nil`. `weakSelf.data = data` will just be a noop and it is a waste of CPU cycles to check for `nil`. – Abhi Beckert Oct 02 '14 at 06:28
  • @AbhiBeckert: If there were only one use of the weak variable, then yes. It there are multiple uses, then there would still be a question of consistency between the uses (in one it might not be `nil` and in another it's `nil`), in cases where that may matter. Of course, if there is deallocation of the object in the middle of the block, then there is a problem with your design. – newacct Oct 02 '14 at 10:02
  • @newacct Assuming there is no multithreading going on... then it is impossible for self to be deallocated in the middle of the block's execution. It will either be nil for the entire thing, or available for the entire thing. If there is multithreading then you need far better protection than this code is providing. – Abhi Beckert Oct 02 '14 at 10:20
  • 1
    @AbhiBeckert: That's not really true. It's possible for a function that is called in the middle of the code to cause the last strong reference to be removed (e.g. you call a delegate method in the middle, and that delegate unsets its instance variable which refers to this object). – newacct Oct 02 '14 at 19:18
  • @newacct in theory yes but but pigs can also fly, in theory. Obj-C was a manual memory managed language for 20 years and I've never seen anyone put `[self retain]` at the beginning of a method or `[self release]` at the end of it. – Abhi Beckert Oct 02 '14 at 23:26

0 Answers0