29

Do we need to use __weak self inside UIAnimation Blocks as given below? Whether it will create retain cycle issue if we are not specifying self as weak?

[UIView animateWithDuration:animationDuration 
                      delay:0 
                    options:UIViewAnimationCurveEaseInOut 
                 animations:^{
        [self doSomething];
    } completion:^(BOOL finished) {
        if (finished) {
            [self doSomething];
        }
    }];

I am also confused in the following scenario. Any thoughts on this? please share your comments.

[self.navController dismissViewControllerAnimated:animated 
                                       completion:^{
                                                      [self doSomething];
                                                  }];

Should we use weak self here?

arango_86
  • 4,236
  • 4
  • 40
  • 46
  • Thank you guys, I am getting clearer and clearer. I would like to discuss the following case as well. [self.navController dismissViewControllerAnimated:animated completion:^{ [self doSomething]; }]; – arango_86 Apr 21 '15 at 11:53

3 Answers3

65

This is not a retain cycle. A retain cycle would be

self -> block -> self

In this case we have

animation framework -> block
block -> self

where the first retain is only temporary - the block gets released when the animation ends. Even if a retain cycle happens, it will be only temporary and it won't prevent object deallocation.

Sulthan
  • 128,090
  • 22
  • 218
  • 270
  • What about the following case void (^animateBlock)(void) = ^(void){ [self doSomething]; }; – arango_86 Apr 21 '15 at 11:32
  • @arango_86 That's the same case you have written in your question. To create a retain cycle, you have to first create a property on your object, e.g. `@property (nonatomic, copy) void (^animateBlock)(void)` and then assign to it `self.animationBlock = ^(void){ [self doSomething]; };`. – Sulthan Apr 21 '15 at 11:40
  • 1
    Using weak self within animation is still good so that it won't prevent the view controller from being released when it goes out of view - and it doesn't make sense to execute the animation when view controller is no longer in view. – Boon Mar 23 '17 at 14:28
  • 2
    @Boon If a view is not in the hierarchy, no animation is actually performed and the callback is called immediately. – Sulthan Mar 23 '17 at 14:50
  • @Sulthan There is no harm in doing it though right? In Swift you in fact get a weak self from within the animation block. – Boon Mar 23 '17 at 15:54
  • What if UIViewAnimationOptionRepeat is used so that animation is never finished? – Leszek Szary Oct 30 '19 at 12:52
6

You need to use __weak when retain cycle is possible. This is not that case because animations block is not retained by self.

Another situation to use __weak is a prolonged action that will call our block after completion and self can be deallocated during this action. For example, some network request will call interface update for our view controller in completion block. User can exit our screen during request. In this situation no need to retain self with a block, it's better to use weak self. But using animation blocks is not this situation too.

Vlad
  • 7,199
  • 2
  • 25
  • 32
3

No, it won't create a retain cycle, because the block (closure) is not attached to self.
For more information, please check out Apple's Automatic Reference Counting.

Fengson
  • 4,751
  • 8
  • 37
  • 62