Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 785
Drew_TwistedPair Avatar asked Dec 09 '25 20:12

Drew_TwistedPair


1 Answers

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.

like image 69
Ryan Poolos Avatar answered Dec 12 '25 10:12

Ryan Poolos



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!