UIView animateWithDuration and UIProgressView setProgress

NtskX picture NtskX · May 22, 2014 · Viewed 14.4k times · Source

I want to animate my UIProgressView progression from 0 to 1 during 10 seconds.

Code:

[UIView animateWithDuration:10.0 animations:^{
    [_myProgressView setProgress:1 animated:YES];
} completion:(BOOL finished)^{
    if (finished) NSLog(@"animation finished);
}];

Animation is working fine except that completion and NSLog are always called instantly.

I tried animateWithDuration: withDelay: but the delay is not respected and executed immediately.

Has anyone encountered the same problem?

Thanks for you help.

Answer

paresh picture paresh · May 18, 2016

Its an old problem but I am still posting the solution here. The solution turned out to be really simple. All you need to do is:

[_myProgressView setProgress:1];
[UIView animateWithDuration:10.0 animations:^{
    [_myProgressView layoutIfNeeded];
} completion:^(BOOL finished){
    if (finished) NSLog(@"animation finished");
}];

Here is a good explanation for why things were working incorrectly for you: http://blog.spacemanlabs.com/2012/08/premature-completion-an-embarrassing-problem/

So you can not use setProgress:animated: method to animate the progress view and get your desired behaviour of completion block as well. However, just setting progress inside the block will not animate it, since progress is not an animatable property.

Refer to apple documentation which says its necessary for the property to be animatable: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/#//apple_ref/occ/clm/UIView/animateWithDuration:animations:

So you just update the value of progress property outside the animate block and do the layout of the view inside the animate block.