swiftxcodeios10uiviewpropertyanimator

Swift UIViewPropertyAnimator automatically plays when leaving app


Good day everyone!

I've a problem with my app. I'm using an UIViewPropertyAnimator to animate my blur. I let the blur effect run from nil (0) to .light (1) but because the light effect is just too much I set the UIViewPropertyAnimator to 0.1 (.fractioncomplete = 0.1).

This works greath! But the problem is that if you leave the app (not kill, just leaving by pressing home button or going to another app), it automatically plays and goes from 0.1 to 1.

I think this is a bug? I hope someone has a solution for this.

Here some pictures: (not enough reputation to post them directly)

picture with blur on 0.1

picture with blur on 1

Code:

let effectView = UIVisualEffectView(effect: nil)
var animator: UIViewPropertyAnimator?

viewdidload:

effectView.frame = view.bounds
effectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
mainView.addSubview(effectView)
animator = UIViewPropertyAnimator(duration: 1, curve: .linear) {
   self.effectView.effect = UIBlurEffect(style: .light)
}

blur action (need to start/pause first because of a known bug from apple to wake the animator up):

self.animator?.startAnimation()
self.animator?.pauseAnimation()
self.animator?.fractionComplete = CGFloat(0.1)

Thanks in advance !


Solution

  • I reproduced your issue, and confirm this behavior, but I doubt it's a bug. Property animator just returns from paused state to active and runs animation. To overcome it you have to stop it and then finish in current fraction of the state (respective states are described in docs). One more issue here - somehow stopping it right after setting fractionComplete stops it at 0 so you have to wait a while (very short). Try this code under your "blurAction":

        self.animator?.startAnimation()
        self.animator?.pauseAnimation()
        self.animator?.fractionComplete = CGFloat(0.1)
    
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { 
            self.animator?.pauseAnimation()
            self.animator?.stopAnimation(true)
            self.animator?.finishAnimation(at: .current)
        }
    

    I verified it works for background/foreground app lifecycle change.