停止调用 -removeAllAnimaitions

Stop the call of -removeAllAnimaitions

目前在iOS平台上,当按下主页按钮时,-removeAllAnimations被发送到每个视图的layer 属性。

迫切需要停止这种行为!

我目前正在使用 CABasicAnimation 动画绘制圆作为计时器。

这是该过程的 gif。计时器启动,动画开始流畅(原谅可怜的 fps)。按下主页按钮并返回应用程序后,动画立即结束。

我正在使用 - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag 方法来检测计时器何时停止。这一切都非常顺利,直到我按下主页按钮。

按下主页按钮会立即完成动画并提前完成计时器。

是否有 任何 方法来停止这种行为,例如 UIViewController 上的方法或我可以在 .plist 中设置的某些 属性我的项目?

这是我第一个陈述的来源。 CABasicAnimation disappear when home button is pushed

这是我目前尝试解决问题的方法。

  1. Subclass CALayer 覆盖 -removeAllAnimations 以防止动画停止。
  2. CALayer class 的扩展中的 +load 方法中执行方法调配,将 -removeAllAnimations 调配成一些伪造的方法。我确定正在调用伪造的方法,但仍然遇到相同的行为。

我创建了一个示例,使用 CABasicAnimation 为 CALayer 的位置设置动画。

想法是在应用程序进入后台时存储动画的一些上下文,并在应用程序返回时恢复动画。

@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"] ;
    }
}

首先感谢@KudoCC 的回复

虽然给定的解决方案可能有效,但我发现 -[CAAnimation removedOnCompletion] 属性.

更简单
CAAnimation * anim = ...;
anim.removedOnCompletion = NO;
// anim will now continue after home button press

此解决方案似乎覆盖了 OS 在按下主页按钮时发出的 -[CALayer removeAllAnimations] 默认调用。