So I have done animations based with the help of method animateWithDuration but i need to stop animation when app goes in background and resume when app comes back in foreground.
Is there a way i can achieve this:-
My animations : label fade in fade out after certain intervals;
- (void)viewDidLoad {
[super viewDidLoad];
[self MyLabelAnimation];
}
- (void)MyLabelAnimation {
self.myLabel.text = @"Text 1";
[UIView animateWithDuration:0.3 animations:^{
self.myLabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:2.7 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.myLabel.alpha = 0.0;
} completion:^(BOOL finished) {
self.myLabel.text = @"Text 2";
[UIView animateWithDuration:0.3 animations:^{
self.myLabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:2.7 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.myLabel.alpha = 0.0;
} completion:^(BOOL finished) {
self.myLabel.text = @"Text 3";
[UIView animateWithDuration:0.3 animations:^{
self.myLabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:2.7 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.myLabel.alpha = 0.0;
} completion:^(BOOL finished) {
self.myLabel.text = @"Text 4";
[UIView animateWithDuration:0.3 animations:^{
self.myLabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.0 delay:4.8 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.myLabel.alpha = 0.0;
} completion:^(BOOL finished) {
[self MyLabelAnimation];
}];
}];
}];
}];
}];
}];
}];
}];
}
Since your animation appears to be a sequence of several smaller sub-animations repeated ad infinitum, you could keep track of where you are in the animation loop at all times, stop the animation when your app becomes inactive, and restart the animation when your app becomes active again.
[Edit: sample code and explanations added below.]
In ViewController.m
:
@interface ViewController ()
{
int numStages; // 4 * 3 = 12 in our example (4 different text labels,
// with 3 substages (alpha ramping up, alpha constant, and alpha ramping down) for each)
int globalStage; // varies from 0 to numStages - 1. 0 initially
bool animationIsActive;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
numStages = 4 * 3; // 4 * 3 = 12 in our example (4 different text labels,
// with 3 substages for each text label's appearance (alpha ramping up, alpha constant, and alpha ramping down))
globalStage = 0; // varies from 0 to numStages - 1. 0 initially
animationIsActive = NO;
self.myLabel.alpha = 0.0;
}
- (void)animateStage:(int)stage {
NSLog(@"animateStage called with argument stage = %d", stage);
// make a note in our instance variable of where we need to restart
// the animation THE NEXT TIME if it is interrupted or paused
// during the current animation:
globalStage = (stage + 1) % numStages;
self.myLabel.text = [NSString stringWithFormat:@"Text %d", (stage / 3) + 1];
switch (stage % 3) {
case 0: // ramp up alpha from 0 to 1
{
[UIView animateWithDuration:0.3 animations:^{
self.myLabel.alpha = 1.0;
} completion:^(BOOL finished) {
// only proceed to next stage if the animation is supposed to be active:
if (animationIsActive) {
[self animateStage:globalStage];
}
}];
}
break;
case 1: // keep alpha constant at 1 (see comment below)
{
[UIView animateWithDuration:2.7 animations:^{
self.myLabel.alpha = 0.99999; // changing the 0.99999 to 1.0 causes
// this stage to be short-circuited. probably because iOS realizes
// that alpha is not really changing in this stage and, being too clever
// by half, decides to skip this stage altogether. but 0.99999 is
// as close to 1.0 as makes no difference.
} completion:^(BOOL finished) {
// only proceed to next stage if the animation is supposed to be active:
if (animationIsActive) {
[self animateStage:globalStage];
}
}];
}
break;
case 2: // ramp down alpha from 1 to 0
{
[UIView animateWithDuration:0.3 animations:^{
self.myLabel.alpha = 0.0;
} completion:^(BOOL finished) {
// only proceed to next stage if the animation is supposed to be active:
if (animationIsActive) {
[self animateStage:globalStage];
}
}];
}
break;
default:
break;
}
}
- (void)viewWillAppear:(BOOL)animated
{
NSLog(@"viewWillAppear: called");
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(didBecomeActive:)
name:UIApplicationDidBecomeActiveNotification
object:[UIApplication sharedApplication]];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(willResignActive:)
name:UIApplicationWillResignActiveNotification
object:[UIApplication sharedApplication]];
}
- (void)viewDidDisappear:(BOOL)animated
{
NSLog(@"viewDidDisappear: called");
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:UIApplicationDidBecomeActiveNotification
object:[UIApplication sharedApplication]];
[[NSNotificationCenter defaultCenter]
removeObserver:self
name:UIApplicationWillResignActiveNotification
object:[UIApplication sharedApplication]];
}
- (void)didBecomeActive:(NSNotification *)notification
{
NSLog(@"view controller's didBecomeActive: called");
// start the animation is we are stopped
if (!animationIsActive)
{
NSLog(@"animation being (re)started at stage %d", globalStage);
[self animateStage:globalStage];
animationIsActive = YES;
}
}
- (void)willResignActive:(NSNotification *)notification
{
NSLog(@"view controller's willResignActive: called");
// stop the animation
NSLog(@"animation being stopped at stage %d", globalStage);
animationIsActive = NO;
}
@end
- I've broken up and "flattened" your animation into 4 * 3 = 12 stages for finer control.
- The instance variables
globalStage
and animationIsActive
are used to keep track of where we are in the animation and whether or not the animation is running.
- In
viewWillAppear:
we ask to be notified when the app becomes active or inactive. When these events occur, our methods didBecomeActive:
or willResignActive:
are called. These two methods are where we (re)start and stop our animations.
- Don't forget to unregister for the two
UIApplication
notifications in viewDidDisappear:
.