iOS, Restarting animation when coming out of the background iOS, Restarting animation when coming out of the background ios ios

iOS, Restarting animation when coming out of the background


well the answer of @dany_23 could work.

But I came across an other method that works just fine if you don't need to resume your animation but restart your animation, without the view or layer snapping when you reactivate the app.

in the

- (void)applicationWillResignActive:(UIApplication *)application

you call a method in your viewcontroller which implements the following code.

[view.layer removeAllAnimations]; // this following CGRect is the point where your view originally started [bg setFrame:CGRectMake(0, 0, 1378, 1005)]; 

and in the

- (void)applicationDidBecomeActive:(UIApplication *)application

you call a method in your viewcontroller that just starts the animation.something like

[UIView animateWithDuration:60 delay:0 options:(UIViewAnimationOptionCurveLinear |UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat | UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState) animations:^{      [bg setFrame:CGRectMake(0, 0, 1378, 1005)];} completion:nil];

Hope this helps, Thanks to all who replied.


You can add an observer in your class for UIApplicationWillEnterForegroundNotification:

- (void)addNotifications {     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillEnterForeground) name:UIApplicationWillEnterForegroundNotification object:nil]; }- (void)applicationWillEnterForeground {     [self animate]; }- (void)animate {     [bg setFrame:CGRectMake(0, 0, 0, 0)];     [UIView animateWithDuration:60 delay:0 options:(UIViewAnimationOptionCurveLinear |UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat | UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState) animations:^{        [bg setFrame:CGRectMake(0, 0, 1378, 1005)];    } completion:nil];}

It is important to set the begin state of the animation (and don't forget to remove the notification observer)


There is a better soloution here than restarting whole animation each time you come from background.

For Swift 3 you can subclass this class:

class ViewWithPersistentAnimations : UIView {    private var persistentAnimations: [String: CAAnimation] = [:]    private var persistentSpeed: Float = 0.0    override init(frame: CGRect) {        super.init(frame: frame)        self.commonInit()    }    required init?(coder aDecoder: NSCoder) {        super.init(coder: aDecoder)        self.commonInit()    }    func commonInit() {        NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil)        NotificationCenter.default.addObserver(self, selector: #selector(willResignActive), name: NSNotification.Name.UIApplicationDidEnterBackground, object: nil)    }    deinit {        NotificationCenter.default.removeObserver(self)    }    func didBecomeActive() {        self.restoreAnimations(withKeys: Array(self.persistentAnimations.keys))        self.persistentAnimations.removeAll()        if self.persistentSpeed == 1.0 { //if layer was plaiyng before backgorund, resume it            self.layer.resume()        }    }    func willResignActive() {        self.persistentSpeed = self.layer.speed        self.layer.speed = 1.0 //in case layer was paused from outside, set speed to 1.0 to get all animations        self.persistAnimations(withKeys: self.layer.animationKeys())        self.layer.speed = self.persistentSpeed //restore original speed        self.layer.pause()    }    func persistAnimations(withKeys: [String]?) {        withKeys?.forEach({ (key) in            if let animation = self.layer.animation(forKey: key) {                self.persistentAnimations[key] = animation            }        })    }    func restoreAnimations(withKeys: [String]?) {        withKeys?.forEach { key in            if let persistentAnimation = self.persistentAnimations[key] {                self.layer.add(persistentAnimation, forKey: key)            }        }    }}extension CALayer {    func pause() {        if self.isPaused() == false {            let pausedTime: CFTimeInterval = self.convertTime(CACurrentMediaTime(), from: nil)            self.speed = 0.0            self.timeOffset = pausedTime        }    }    func isPaused() -> Bool {        return self.speed == 0.0    }    func resume() {        let pausedTime: CFTimeInterval = self.timeOffset        self.speed = 1.0        self.timeOffset = 0.0        self.beginTime = 0.0        let timeSincePause: CFTimeInterval = self.convertTime(CACurrentMediaTime(), from: nil) - pausedTime        self.beginTime = timeSincePause    }}

It will take care of pausing all your animations in current state and re-adding it when app comes from background - without resetting them.

Gist: https://gist.github.com/grzegorzkrukowski/a5ed8b38bec548f9620bb95665c06128