Reputation: 6831
Currently on the iOS platform, when the home button is pressed, -removeAllAnimations
is sent to each view's layer
property.
I am currently using a CABasicAnimation
that animates the drawing of a circle to act as a timer.
Here is a gif of the process. The timer starts and the animation begins smoothly (pardon the poor fps). Once the home button is pressed and I come back to the app, the animation immediately finishes.
I am using the - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
method to detect when the timer is stopped. This is all working out really well, until I press the home button.
Pressing the home button immediately completes the animation and prematurely completes the timer.
Is there any way to stop this behavior such as a method on UIViewController
or some property I can set in the .plist
of my project?
Here is the source for my first statement. CABasicAnimation disappear when home button is pushed
Here are my current attempts to solve the problem.
CALayer
to override -removeAllAnimations
in hope of preventing the stopping of the animation.+load
method in an extension on the CALayer
class that swizzles -removeAllAnimations
to some bogus method. I have determined that the bogus method is being called, yet the same behavior is still being experienced.Upvotes: 4
Views: 209
Reputation: 6831
First off, I want to thank @KudoCC for the response.
While the given solution might work, I have found an easier way with the -[CAAnimation removedOnCompletion]
property.
CAAnimation * anim = ...;
anim.removedOnCompletion = NO;
// anim will now continue after home button press
This solution seems to override the default calls of -[CALayer removeAllAnimations]
issued by the OS when the home button is pressed.
Upvotes: 2
Reputation: 6952
I create an example to animate the position of a CALayer using CABasicAnimation
.
The idea is to store some context of the animation when app goes to background and restore the animation when app goes back.
@interface ViewController ()
{
BOOL animationStoped ;
CFTimeInterval time ;
CGPoint position ;
}
@property (nonatomic, strong) UIView *viewAnimate ;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_viewAnimate = [[UIView alloc] initWithFrame:CGRectMake(0.0, 100.0, 100.0, 100.0)] ;
_viewAnimate.backgroundColor = [UIColor redColor] ;
[self.view addSubview:_viewAnimate] ;
CABasicAnimation *animation = [self animation] ;
[_viewAnimate.layer addAnimation:animation forKey:@"animation.position"] ;
_viewAnimate.layer.position = CGPointMake(250.0, 350.0) ;
time = [_viewAnimate.layer convertTime:CACurrentMediaTime() fromLayer:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleEnterBackgroundNotification:)
name:UIApplicationDidEnterBackgroundNotification
object:nil] ;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleDidBecomeActiveNotification:)
name:UIApplicationDidBecomeActiveNotification
object:nil] ;
}
- (CABasicAnimation *)animation
{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"] ;
animation.fromValue = [NSValue valueWithCGPoint:CGPointMake(50.0, 50.0)] ;
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(250.0, 350.0)] ;
animation.duration = 5.0 ;
animation.delegate = self ;
return animation ;
}
- (void)handleEnterBackgroundNotification:(id)nty
{
CAAnimation *aa = [_viewAnimate.layer animationForKey:@"animation.position"] ;
animationStoped = aa != nil ;
if (animationStoped) {
CALayer *presentationLayer = _viewAnimate.layer.presentationLayer ;
position = presentationLayer.position ;
CFTimeInterval now = [_viewAnimate.layer convertTime:CACurrentMediaTime() fromLayer:nil];
time = now - time ;
}
}
- (void)handleDidBecomeActiveNotification:(id)nty
{
if (animationStoped) {
CABasicAnimation *animation = [self animation] ;
animation.fromValue = [NSValue valueWithCGPoint:position] ;
animation.duration -= time ;
[_viewAnimate.layer addAnimation:animation forKey:@"animation.position"] ;
}
}
Upvotes: 2