1

I know that when we're using ARC and blocks, we should use __weak to prevent capturing strongly self and prevent a retain cycle ! But I was wondering if in the following example I need to use __weak ?

__weak MyViewController *weakSelf = self;
[self.personObject.gallery downloadLogoCompletionBlock:^(UIImage *image) {
                                        if (image) {
                                            weakSelf.logoImageView.image = image;
                                        }];

Gallery is retaining the block not self, right ? If so I could write :

self.logoImageView.image = image;

Thanks for your answers

SJ17
  • 13
  • 3

3 Answers3

0

With a strong reference self inside the block you would have a (temporary) retain cycle

self -> _personObject -> _gallery -> BLOCK -> self

assuming that the properties personObject, gallery are backed up by instance variables _personObject, _gallery. The retain cycle will be "destroyed" as soon as the completion block is called. If the completion block is never called then self can never be deallocated.

Therefore, if self should possibly be deallocated before the completion block is called, you should use a weak reference.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • But what happens when an object is deallocated while a method of the object is still running? – trojanfoe Oct 17 '13 at 14:43
  • @trojanfoe: Which object and which method are you referring to in this case? – Martin R Oct 17 '13 at 14:47
  • `personObject.gallery downloadLogoCompletionBlock`. I would have thought the answer to my question is "all hell breaks lose", just like every other programming language, however there is no guarantee that the completion block will be called at all (due to a bug for example), so the point you make about that is critical. – trojanfoe Oct 17 '13 at 14:49
  • @trojanfoe: With a strong reference in the block, `self` would be kept alive until the block is destroyed. A weak reference in the block is normally made strong with `MyViewController *strongSelf = weakSelf` to keep it alive while the block is executing. In both cases, `self` would be not be deallocated while the completion block is running – Martin R Oct 17 '13 at 14:56
  • @MartinR Ok so if I understand it right the following is right because the current VC can't be deallocated before twitterVC, right ? `TWTweetComposeViewController *tweetComposeVC = [[TWTweetComposeViewController alloc] init]; [tweetComposeVC setInitialText:initialText]; [tweetComposeVC setCompletionHandler:^(TWTweetComposeViewControllerResult result) { [self dismissViewControllerAnimated:YES completion:NULL]; }]; [self presentViewController:tweetComposeVC animated:YES completion:NULL];` – SJ17 Oct 17 '13 at 15:00
  • @SJ17: I haven't worked with TWTweetComposeViewController yes, but from the retain cycle point of view that looks OK to me, because you *know* that the completion handler will be called eventually. – Martin R Oct 17 '13 at 15:05
0

It depends.

Lets say you pop this MyViewController instance from a navigation controller and you expect it to deallocate.

Assuming gallery holds a strong reference to the block, if you didn't use a weak reference you will run into a retain cycle.

personObject.gallery won't get deallocated, because your view controller didn't get deallocated either, since it is getting retained by personObject.gallery's block in the first place.

The other scenario is that gallery does not retain the block, in which case you won't run into the retain cycle.

If for some reason, you don't what goes on with the block inside the implementation of gallery, it's always a good idea to use a weak reference, just in case!

Pedro Mancheno
  • 5,237
  • 4
  • 24
  • 31
0

This would cause an cycle, just longer than many.

self -> personObject -> gallery -> block
  ^---------------------------------|

However, this block will live only long enough to be called once, then the gallery should release it, breaking the cycle.

Kevin
  • 53,822
  • 15
  • 101
  • 132