UIView animation block: if duration is 0, is it the same as without animation?
Asked Answered
C

7

22

I need to handle a case where you can do something with or without animation, instead of:

if (animation)
{
    [UIView animateWithBlock:^(){...}];
}
else
{
    ...
}

I want to do:

[UIView animateWithBlock:^(){...} duration:(animation ? duration : 0)]

but not sure if it works, even if it does, is there any overhead for using this instead of directly change the view?

Thanks

Correia answered 13/11, 2012 at 22:21 Comment(0)
D
8

Yes, since the duration is zero, the transition will effectively by instantaneous.

Dole answered 13/11, 2012 at 22:28 Comment(4)
And does it have any overhead? ie. [UIView animateWithBlock:^(){self.view.frame = newFrame} withDuration:0] vs self.view.frame = newFrame?Correia
You would need to set the frame first so it will act like any other frame. - Yes it will have an overhead.Dole
I tested this with iOS 7.1.1 5S and the difference is huge; setting a random frame for a view 10k times took 22.85 seconds with ^animateWithBlock:^ and 0.05 seconds with a direct call to the block. However, if you're preforming only a few animation calls for some user interaction, the difference is not relevant. Please note that Apple might change the behavior and optimize this edge case in the future.Benison
This answer is no longer accurate. A setting of 0 will not occur instantaneously, it will take a default period of time somewhere close to 0.25sec.Ananias
N
31

What I do in this cases, is to create a block that contains all the animations I want to make. Then execute an UIView animation passing the animation block as a parameter, or directly calling that block, whether I want it to be animated or not. Something like this :

void (^animationBlock)();
animationBlock=^{
      // Your animation code goes here
};
if (animated) {
    [UIView animateWithDuration:0.3 animations:animationBlock completion:^(BOOL finished) {

    }];
}else{
    animationBlock();
}

That would avoid the overhead

Needlewoman answered 29/12, 2012 at 22:52 Comment(0)
S
22

According to the Apple docs:

If the duration of the animation is 0, this block is performed at the beginning of the next run loop cycle.

Sharolynsharon answered 19/3, 2013 at 6:4 Comment(3)
So it may not be actually 0 delays from the time the animation statement is executed?Correia
@Correia exactly. The effect is the same as calling [self performSelector:@selector(animate) afterDelay:0]Sharolynsharon
I can confirm this is indeed the case. Using 0 is not equal to not animating and performing it immediately.Gottuard
D
8

Yes, since the duration is zero, the transition will effectively by instantaneous.

Dole answered 13/11, 2012 at 22:28 Comment(4)
And does it have any overhead? ie. [UIView animateWithBlock:^(){self.view.frame = newFrame} withDuration:0] vs self.view.frame = newFrame?Correia
You would need to set the frame first so it will act like any other frame. - Yes it will have an overhead.Dole
I tested this with iOS 7.1.1 5S and the difference is huge; setting a random frame for a view 10k times took 22.85 seconds with ^animateWithBlock:^ and 0.05 seconds with a direct call to the block. However, if you're preforming only a few animation calls for some user interaction, the difference is not relevant. Please note that Apple might change the behavior and optimize this edge case in the future.Benison
This answer is no longer accurate. A setting of 0 will not occur instantaneously, it will take a default period of time somewhere close to 0.25sec.Ananias
G
4

I wrote this little Swift extension to overcome the issue:

extension UIView {

/// Does the same as animate(withDuration:animations:completion:), yet is snappier for duration 0
class func animateSnappily(withDuration duration: TimeInterval, animations: @escaping () -> Swift.Void, completion: (() -> Swift.Void)? = nil) {
    if duration == 0 {
        animations()
        completion?()
    }
    else {
        UIView.animate(withDuration: duration, animations: animations, completion: { _ in completion?() })
    }
}
}

One can use it as a replacement for UIView.animate(withDuration:animations:completion) and doesn't have to make any more thoughts about duration 0.

Gumption answered 3/3, 2017 at 14:39 Comment(0)
B
2

Okay, I have further observation on this. Firsth, there is a performance overhead when using the animation with zero duration but the more profound difference is that the animation's completion block is handled async. This means that first hiding and then displaying the view might not get you the result you expected.

So, no, I would definitely suggest not to use the zero as a duration as it's not synchronous.

Benison answered 30/6, 2014 at 5:49 Comment(0)
A
0

you can set animateWithDuration value dynamically as per requirement.

If You set 0. it means no animation transition time.So, View will be appear without any animation. IF you want provide animation, set some value more than 0.

    **float animationDurationValue=0.03f;
        [UIView animateWithDuration:x delay:0.0f options:UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse 
animations:^{
                             [yourView setFrame:CGRectMake(0.0f, 100.0f, 300.0f, 200.0f)];
                         }
                         completion:nil];**

Please let me know if any issue.

Adkinson answered 19/3, 2013 at 6:14 Comment(0)
J
0

As answered, it is not. Here is an example of how to do it in swift.

let setHighlighted: (Bool) -> Void = { [weak self] highlighted in
   if highlighted {
      self?.cardView.alpha = 0.6
   } else {
      self?.cardView.alpha = 1.0
   }
 }

 if animated {
    UIView.animate(withDuration: yourDuration) {
       setHighlighted(highlighted)
    }
 } else {
    setHighlighted(highlighted)
 }
Jarman answered 29/11, 2022 at 21:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.