14

Inside a UIView animation block, is there a way to get the current animation's duration?

[UIView animateWithDuration:1.0 animations:^{
    // float duration = ?
}];
adamsiton
  • 3,642
  • 32
  • 34

5 Answers5

5

If you are targeting iOS 9.0 or later, then you are looking for a class property of UIView, called inheritedAnimationDuration.

Usage:

let currentAnimationDuration = UIView.inheritedAnimationDuration

From Apple docs:

Summary

Returns the inherited duration of the current animation.

Discussion

This method only returns a non-zero value if called within a UIView animation block.

Dennis Pashkov
  • 934
  • 10
  • 24
3

TL;DR: use CALayer -actionForKey:, not -animationForKey:

@Dimitri Bouniol 's answer didn't work for me when called from an an affected setter inside an animation block. The reason, from my understanding, is that UIView's animation system sets up state before starting the actual animation (and calls setters before starting the actual animation). What worked for me though was calling the similar -actionForKey: method on the layer. The action returned did have the proper duration set, and can be used as it is in his answer.

CAAnimation *animation = (CAAnimation *)[self.layer actionForKey@"position"]; // or property of interest

[CATransaction begin];
[CATransaction setAnimationDuration:animation.duration];
[CATransaction setAnimationTimingFunction:animation.timingFunction];

// CALayer animation here

[CATransaction commit];
Iulian Onofrei
  • 9,188
  • 10
  • 67
  • 113
Chris Conover
  • 8,889
  • 5
  • 52
  • 68
  • Doesn't work in iOS 11. `actionForKey:` returns a `_UIViewAdditiveAnimationAction` that conforms to the `CAAction` protocol but is not a `CAAnimation`. So the `timingFunction` property doesn't exist. @Dimitri Bouniol's answer works for me. – Ortwin Gentz Apr 24 '18 at 11:35
1

[CATransaction animationDuration] is what you're looking for

Nick Dowell
  • 2,030
  • 17
  • 17
0

Since you're using blocks, why not just capture a variable with it?

CGFloat duration = 1.0;
[UIView animateWithDuration:duration animations:^{ 
    CGFloat theDuration = duration; 
}];
Rollin_s
  • 1,983
  • 2
  • 18
  • 18
0

You can get the current animation easily enough. For instance, setting up a CATransaction:

CAAnimation *animation = [self.layer animationForKey:self.layer.animationKeys.firstObject];
[CATransaction begin];
[CATransaction setAnimationDuration:animation.duration];
[CATransaction setAnimationTimingFunction:animation.timingFunction];

// CALayer animation here

[CATransaction commit];
Dimitri Bouniol
  • 735
  • 11
  • 15