16

I have an image, I animate it with this code, in viewDidAppear:

UIView.animateWithDuration(10.5, delay:0.0, options: [], animations:{
self.myImage.transform = CGAffineTransformMakeTranslation(0.0, 200)
}, completion: nil)

I want to pause the animation when I tap myPauseButton, and resume the animation if I tap it again.

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Simon Derek
  • 183
  • 1
  • 1
  • 9

3 Answers3

41

2 functions to pause and resume animation, I take from here and convert to Swift.

func pauseLayer(layer: CALayer) {
    let pausedTime: CFTimeInterval = layer.convertTime(CACurrentMediaTime(), from: nil)
    layer.speed = 0.0
    layer.timeOffset = pausedTime
}

func resumeLayer(layer: CALayer) {
    let pausedTime: CFTimeInterval = layer.timeOffset
    layer.speed = 1.0
    layer.timeOffset = 0.0
    layer.beginTime = 0.0
    let timeSincePause: CFTimeInterval = layer.convertTime(CACurrentMediaTime(), from: nil) - pausedTime
    layer.beginTime = timeSincePause
}

I have a button to pause or resume the animation which is initiated in viewDidLoad:

var pause = false
override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    UIView.animate(withDuration: 10.5) {
        self.image.transform = CGAffineTransformMakeTranslation(0.0, 200)
    }
}

@IBAction func changeState() {
    let layer = image.layer
    pause = !pause
    if pause {
        pauseLayer(layer)
    } else {
        resumeLayer(layer)
    }
}
Kyle Redfearn
  • 2,172
  • 16
  • 34
t4nhpt
  • 5,264
  • 4
  • 34
  • 43
12

Here is Swift 3 version of that answer + I moved those function to an extension

extension CALayer {
    func pause() {
        let pausedTime: CFTimeInterval = self.convertTime(CACurrentMediaTime(), from: nil)
        self.speed = 0.0
        self.timeOffset = pausedTime
    }

    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
    }
}
Grzegorz Krukowski
  • 18,081
  • 5
  • 50
  • 71
12

Since iOS 10 provides UIViewPropertyAnimator you can solve your problem easier.

Declare these properties in your controller:

var animationPaused = false
lazy var animator: UIViewPropertyAnimator = UIViewPropertyAnimator(duration: 10.5, curve: .easeInOut, animations: {

    self.myImage.transform = CGAffineTransform(translationX: 0.0, y: 200)
})

Add the following code to the tap handler of myPauseButton:

if self.animator.state == .active { // Don't start or pause the animation when it's finished

    self.animationPaused = !self.animationPaused
    self.animationPaused ? self.animator.pauseAnimation() : self.animator.startAnimation()
}

Start the animation in viewDidAppear(_ animated: Bool) with these lines of code:

self.animationPaused = false
self.animator.startAnimation()
Roman Podymov
  • 4,168
  • 4
  • 30
  • 57