Search code examples
iphoneiosobjective-cuiviewanimationuicolor

Best way to handle a chain of animations with UIViewAnimations


I am build an iOS application in which I have a requirement for the backgroundColor of the view to animation through a selection of colors. In my viewDidLoad method I am basically firing off a chain of UIView animations using the following.

-(void) beginFirstStageBackgroundAnimation
{
    [UIView animateWithDuration: 3.0f
                          delay: 3.0f
                        options: UIViewAnimationOptionTransitionCrossDissolve
                     animations:^{
                         self.view.backgroundColor = [UIColor colorWithRed: 251./255 green:203./255 blue:147./255 alpha:1.0];
                     }
                     completion:^(BOOL finished){
                         [self secondStageBackgroundAnimation];
                     }
     ];
}

The completion handler fires the second method containing the next color....

-(void) secondStageBackgroundAnimation
{
    [UIView animateWithDuration: 3.0f
                          delay: 3.0f
                        options: UIViewAnimationOptionTransitionCrossDissolve
                     animations:^{
                         self.view.backgroundColor = [UIColor colorWithRed:251./255 green:224./255 blue:96./255 alpha:1.0];
                     }
                     completion:^(BOOL finished){
                         [self thirdStageBackgroundAnimation];
                     }
     ];
}

And so on...this goes on until in the seventh animation I call [self beginFirstStageBackgroundAnimation]; in the completion to begin the process again.

When the I leave the view with the back button, in viewDidDisappear or when the timer on the display ends I run [self.view.layer removeAllAnimations]; to entirely get rid of the animations. However, the app runs and works exactly as intended but seems to be crashing after leaving the view and running for a whole and although I don't know why yet it seems related to this animation chain.

Is there a better solution to animate the backgroundColor of the view every 3 seconds with a 3 second delay?

And does [self.view.layer removeAllAnimations]; actually do what I want?

EDIT: The code where I leave the view is as follows:

-(void) backBtnPressed:(id)sender
{
    [self stopAudio]; // stop audio that is playing.
    [self.view.layer removeAllAnimations]; // remove all animations?
    [self.navigationController popViewControllerAnimated: YES]; // pop view from stack
}

Solution

  • You can try to use CAAnimation I think it will be easier to you to manage colors and animations

    - (void)viewDidAppear:(BOOL)animated
    {
        [super viewDidAppear:animated];
        NSArray *colors = @[[UIColor greenColor],
                            [UIColor redColor],
                            [UIColor blueColor],
                            [UIColor yellowColor],
                            [UIColor orangeColor]
                            ];
        NSMutableArray *animations = [NSMutableArray new];
        float colorAnimationDuration = 3.0f;
        for (int i = 0; i < colors.count; i++)
        {
            CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
            animation.toValue = (id)[[colors objectAtIndex:i] CGColor];
            animation.duration = colorAnimationDuration;
            animation.beginTime = i * colorAnimationDuration;
            animation.removedOnCompletion = NO;
            animation.fillMode = kCAFillModeForwards;
    
            [animations addObject:animation];
        }
    
        CAAnimationGroup *animationsGroup = [CAAnimationGroup new];
        animationsGroup.duration = colors.count * colorAnimationDuration;
        animationsGroup.repeatCount = HUGE_VALF;
        animationsGroup.animations = animations;
    
        [self.view.layer addAnimation:animationsGroup forKey:@"myAnimations"];
    
    }
    
    - (void)viewWillDisappear:(BOOL)animated
    {
        [super viewWillDisappear:animated];
        [self.view.layer removeAnimationForKey:@"myAnimations"];
    }