5

在我的应用程序中,我有一个沿着 bezierPath 动画的 CALayer 数组。当我关闭并重新打开应用程序时,我的图层没有动画,并且与关闭应用程序之前的位置不同。我已经实现了两种方法,pauseLayer 和 resumeLayer,当我在我的应用程序中使用两个按钮触发它们时它们会起作用,但在关闭应用程序后它们将不起作用。代码如下

   - (void)pauseLayers{

    for(int y=0; y<=end;y++)
    {



        CFTimeInterval pausedTime = [car[y] convertTime:CACurrentMediaTime() fromLayer:nil];
        car[y].speed = 0.0;
        car[y].timeOffset = pausedTime;

         standardUserDefaults[y] = [NSUserDefaults standardUserDefaults];


        if (standardUserDefaults[y]) {
            [standardUserDefaults[y] setDouble:pausedTime forKey:@"pausedTime"];
            [standardUserDefaults[y] synchronize];
        }


        NSLog(@"saving positions");


        }


}

-(void)resumeLayers

{  




    for(int y=0; y<=end;y++)
    {




        standardUserDefaults[y] = [NSUserDefaults standardUserDefaults];     
        car[y].timeOffset = [standardUserDefaults[y] doubleForKey:@"pausedTime"];

    CFTimeInterval pausedTime = [car[y] timeOffset];
    car[y].speed = 1.0;
    car[y].timeOffset = 0.0;
    car[y].beginTime = 0.0;

    CFTimeInterval timeSincePause = [car[y] convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
    car[y].beginTime = timeSincePause;
        }


}
4

4 回答 4

3
- (void)applicationDidEnterBackground:(UIApplication *)application {

 mosquitosViewController *mvc = [[mosquitosViewController alloc] init];
  [mvc pauseLayers];

  }

您在上面尝试做的问题是您正在创建一个全新的视图控制器实例,这不是屏幕上显示的那个。这就是为什么当您发送pauseLayers消息时没有任何反应的原因。

您应该做的是注册以接收有关您的应用程序何时进入和来自后台的通知,并在该通知到达时调用适当的方法 (pauseLayers和)。resumeLayers

您应该在mosquitosViewController实现中的某处添加以下代码(我通常在 viewDidLoad 中这样做):

// Register for notification that app did enter background
[[NSNotificationCenter defaultCenter] addObserver:self 
                                      selector:@selector(pauseLayers)
                                      name:UIApplicationDidEnterBackgroundNotification 
                                      object:[UIApplication sharedApplication]];

// Register for notification that app did enter foreground
[[NSNotificationCenter defaultCenter] addObserver:self 
                                      selector:@selector(resumeLayers) 
                                      name:UIApplicationWillEnterForegroundNotification 
                                      object:[UIApplication sharedApplication]];
于 2011-07-27T18:11:06.863 回答
1

我根据这个线程的@cclogg 和@Matej Bukovinski 的回答编写了一个Swift 4版本扩展。你只需要打电话layer.makeAnimationsPersistent()

完整要点:CALayer+AnimationPlayback.swift, CALayer+PersistentAnimations.swift

核心部分:

public extension CALayer {
    static private var persistentHelperKey = "CALayer.LayerPersistentHelper"

    public func makeAnimationsPersistent() {
        var object = objc_getAssociatedObject(self, &CALayer.persistentHelperKey)
        if object == nil {
            object = LayerPersistentHelper(with: self)
            let nonatomic = objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC
            objc_setAssociatedObject(self, &CALayer.persistentHelperKey, object, nonatomic)
        }
    }
}

public class LayerPersistentHelper {
    private var persistentAnimations: [String: CAAnimation] = [:]
    private var persistentSpeed: Float = 0.0
    private weak var layer: CALayer?

    public init(with layer: CALayer) {
        self.layer = layer
        addNotificationObservers()
    }

    deinit {
        removeNotificationObservers()
    }
}

private extension LayerPersistentHelper {
    func addNotificationObservers() {
        let center = NotificationCenter.default
        let enterForeground = NSNotification.Name.UIApplicationWillEnterForeground
        let enterBackground = NSNotification.Name.UIApplicationDidEnterBackground
        center.addObserver(self, selector: #selector(didBecomeActive), name: enterForeground, object: nil)
        center.addObserver(self, selector: #selector(willResignActive), name: enterBackground, object: nil)
    }

    func removeNotificationObservers() {
        NotificationCenter.default.removeObserver(self)
    }

    func persistAnimations(with keys: [String]?) {
        guard let layer = self.layer else { return }
        keys?.forEach { (key) in
            if let animation = layer.animation(forKey: key) {
                persistentAnimations[key] = animation
            }
        }
    }

    func restoreAnimations(with keys: [String]?) {
        guard let layer = self.layer else { return }
        keys?.forEach { (key) in
            if let animation = persistentAnimations[key] {
                layer.add(animation, forKey: key)
            }
        }
    }
}

@objc extension LayerPersistentHelper {
    func didBecomeActive() {
        guard let layer = self.layer else { return }
        restoreAnimations(with: Array(persistentAnimations.keys))
        persistentAnimations.removeAll()
        if persistentSpeed == 1.0 { // if layer was playing before background, resume it
            layer.resumeAnimations()
        }
    }

    func willResignActive() {
        guard let layer = self.layer else { return }
        persistentSpeed = layer.speed
        layer.speed = 1.0 // in case layer was paused from outside, set speed to 1.0 to get all animations
        persistAnimations(with: layer.animationKeys())
        layer.speed = persistentSpeed // restore original speed
        layer.pauseAnimations()
    }
}
于 2018-04-28T09:02:26.307 回答
0
- (void)applicationDidEnterBackground:(UIApplication *)application

{

NSLog(@"1");
mosquitosViewController *mvc = [[mosquitosViewController alloc] init];
[mvc pauseLayers];

/*
 Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
 If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
 */

}

于 2011-07-24T10:01:14.917 回答
0

有关如何在多任务处理后重新启动动画的详细信息,请参阅我对这篇文章的回答:

当应用程序从后台恢复时恢复动画停止的地方

于 2011-11-02T16:24:14.973 回答