8

We know that UIImageView has a very nice support for image sequence animation. We can easily create an array of UIImage objects, set the animationImages property, configure animation duration, repeat count etc. and then just fire. But there seems to be no way to know when this animation has ended.

Say I have ten images and then I want to run an animation (repeat count = 1) with them. And when the animation is over, I want to run some other code. What is the best way to know that animation has ended?

I already understand that I can create a NSTimer and schedule it to fire after animation duration. But you really cannot rely on timer if you need good precision.

So my question is, is there any better way to know that an UIImageView image sequence animation has ended without using the timer?

The code is something like this

myImageView.animationImages = images; // images is a NSArray of UIImages
myImageView.animationDuration = 2.0;
myImageView.animationRepeatCount = 1;

[myImageView startAnimating]
jszumski
  • 7,430
  • 11
  • 40
  • 53
taskinoor
  • 45,586
  • 12
  • 116
  • 142
  • 1
    Have you actually tried using a timer? It's true that the timing is not 100% accurate but AFAIK you can't rely on the timing of other animations, either. I wouldn't be surprised if the built-in UIImageView animation uses a timer itself. – Ole Begemann Sep 22 '10 at 16:00
  • ya i have tried timer. in fact this is what i am using right now. this is ok for many cases, but well ... not 100% :-) – taskinoor Sep 22 '10 at 16:08
  • 1
    Also note that probably simpler than a timer for a one-shot invocation is the `-performSelector:withObject:afterDelay` method on whatever your target is. It does the timer for you internally. – Ben Zotto Sep 22 '10 at 16:44

3 Answers3

8

The isAnimating property on UIImageView should go to NO when it's done animating. It's not a formal property, though, so you can't set up observation on it. You can poll it on a fine-grained timer (like CADisplayLink's).

There's no "animation completed" delegate for this, if that's the sort of thing you're looking for. The timing can be variable based on loading delay of the images, etc, and no, there's no sure-fire way to know precisely when it's done.

The image animation stuff on UIImageView is a convenience, and not heavyweight enough to do serious animation work with. Consider rolling your own if you need that kind of precision.

Ben Zotto
  • 70,108
  • 23
  • 141
  • 204
  • ya, i also think that eventually i need to handle this on my own. just wanted to be sure that im not missing anything and there is no alternate way. – taskinoor Sep 22 '10 at 16:14
  • Not sure what you mean by "formal property". It's definitely a property, but UIImageView probably doesn't call the setter (I suspect there isn't one). – tc. Sep 23 '10 at 00:28
1

I made this (method of my UIImageView subclass).

-(void)startAnimatingWithCallback:(UIImageViewAnimationCompletitionBlock) completitionCallback
{
    [self startAnimating];

    dispatch_queue_t animatingQueue = dispatch_get_current_queue();
    dispatch_queue_t pollingQueue = dispatch_queue_create("pollingQueue", NULL);
    dispatch_async(pollingQueue, ^{

        while(self.isAnimating) { usleep(10000); }
        dispatch_async(animatingQueue, ^{ if (completitionCallback) completitionCallback(); });

    });
}

Simple usage:

[self.oneView fadeOut];
[self.otherView startAnimatingWithCallback:^
{
    [self.oneView fadeIn];
}];
Geri Borbás
  • 15,810
  • 18
  • 109
  • 172
  • One of the worst hack: the while loop will hog one CPU (up to 100%) and quickly drain the battery. – CouchDeveloper Nov 19 '13 at 17:59
  • Yap actually this "endlessie" loop is not the best idea even in the background. It depends anyway, I've actually used this for a matter of seconds only. – Geri Borbás Nov 19 '13 at 18:21
  • 1
    You could add a `usleep(10000);` to alleviate the problem. Otherwise, you take the risk for being blamed to be the reason of the battery problems on apple devices :P – CouchDeveloper Nov 19 '13 at 18:24
0

Furthermore I could recommend setting default image of the UIImageView (property image) on the first frame of the animation and changing it to the last frame just after launching the animation (startAnimating method). This way we avoid the ugly blick which can occur when the animation is finished but the callback is not invoked.

Kaktusiarz
  • 415
  • 7
  • 22