Drew_TwistedPair
Drew_TwistedPair

Reputation: 100

Adding randomness to looping UIView animation block

I'm trying to make an animation in iOS using the animateWithDuration: method.

I'm moving an image(a simple picture of a cloud in a UIImageView) across the screen and then having that animation run in a loop and I want to change the speed(duration) each time it crosses the screen.

I've tried a couple ways but both behave incorrectly for me.

I first though I could use the UIViewAnimationOptionRepeat like this:

[UIImageView animateWithDuration:arc4random() % 10 + 1
                           delay:0.0
                         options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionRepeat
                      animations:^{
 //moving the cloud across the screen here
}
completion:^(BOOL finished) {
    NSLog(@"Done!");
}];

But this does not seem to call the arc4random() again to reset the duration...i.e. the cloud will cross the screen at a random speed only every time the app is started, not every time the animation loops.

I then tried using the completion block to fire the animation again like this:

-(void)animateMethod
{
[UIImageView animateWithDuration:arc4random() % 10 + 1
                           delay:0.0
                         options:UIViewAnimationOptionCurveLinear
                      animations:^{
 //moving the cloud across the screen here
}
completion:^(BOOL finished) {
    NSLog(@"Done!");
    [self animateMethod];
}];
}

This gives me the effect I'm looking for, but when I push to another view using a navigation controller the completion block gets fired in an unending loop it seems(my log gets spammed with "Done!")

Anyone know the way to get the desired effect I want the proper way?

Upvotes: 3

Views: 1098

Answers (1)

Ryan Poolos
Ryan Poolos

Reputation: 18551

You're on the right track. The key is that you need to only loop if the animation finished not if it failed. So you need to check if the finished BOOL is true before telling it to loop.

-(void)animateMethod
{
    [UIImageView animateWithDuration:arc4random() % 10 + 1
                               delay:0.0
                             options:UIViewAnimationOptionCurveLinear
                          animations:^{
     //moving the cloud across the screen here
    }
    completion:^(BOOL finished) {
        if (finished) {
            NSLog(@"Done!");
            [self animateMethod];
        }
    }];
}

This method works great for very simple animations like this and when you're only doing a few, like maybe 3-5 clouds at a time. Anything more than this and you'll probably want to setup your own animation loop using an NSTimer or CADisplayLink and adjusting the clouds frames in it. Its a much more manual way but it will get you some nice animations even in UIKit.

Upvotes: 5

Related Questions