6

I have a pulse animation that I want to run for 3 or 4 seconds, and am looking for a way to delay and run that animation for that amount of time before segueing to the next screen. I am using the code below for the delay, but it is not working when I call the function.

NSTimer.scheduledTimerWithTimeInterval(NSTimeInterval(3), target: self, selector: "functionHere", userInfo: nil, repeats: false)

Please let me know if you have any ideas.

let pulseAnimation = CABasicAnimation(keyPath: "opacity")
    pulseAnimation.duration = 1
    pulseAnimation.fromValue = 0
    pulseAnimation.toValue = 1
    pulseAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
    pulseAnimation.autoreverses = true
    pulseAnimation.repeatCount = FLT_MAX
    XboxOneL.layer.addAnimation(pulseAnimation, forKey: "animateOpacity")
    XboxOneR.layer.addAnimation(pulseAnimation, forKey: "animateOpacity")
dgelinas21
  • 641
  • 3
  • 9
  • 22
  • [Check if the view is animating](http://stackoverflow.com/questions/5526476/how-to-tell-if-uiview-is-in-middle-of-animation) in `prepareForSegue` and delay accordingly. – brandonscript Feb 07 '17 at 18:20
  • Post your animation code. What kind of animation are you doing? Most of them have a way to set a completion function, which you could use to perform your segue after your animation finishes. – creeperspeak Feb 07 '17 at 18:24
  • Do you want it to be something like; user presses button (or some other action), there is a delay of x, the animation then takes 3 to 4 seconds to happen, finally a segue is fired to another screen? – theMikeSwan Feb 07 '17 at 18:24
  • @theMikeSwan I have the animation set up on a button click. But as it is currently the animation runs forever. When I added the code to segue it to the next view, it segues without animating. So I want the button click to run the animation and delay the segue for like 3 seconds while running the animation, then segue. – dgelinas21 Feb 07 '17 at 19:04
  • Is the method your timer fires getting called? (A breakpoint in the method is the easiest way to tell.) If not try making sure everything is right with the selector you are using. – theMikeSwan Feb 07 '17 at 19:25
  • for some reason I couldn't get the selector method to run. It's called properly but isn't running or producing an error. – dgelinas21 Feb 07 '17 at 23:25

4 Answers4

12

Depending on how your animation is implemented, you could use:

UIView.animate(withDuration: 0.3, delay: 5.0, options: [], animations: { 
//Animations
}) { (finished) in
//Perform segue
}

This will apply a delay before the animations run, then run a completion block (where you execute your segue).

EDIT: You updated your question to use CAAnimations, so I don't think this solution will work.

Matt Beaney
  • 460
  • 4
  • 15
7

If you're looking for a delay which is standard in Swift 3, then it's probably best to use the DispatchQueue API in conjunction with UIView.animate(withDuration:_:).

If for example you wanted to delay a 1.0 second animation by 3 seconds:

let yourDelay = 3
let yourDuration = 1.0
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(yourDelay), execute: { () -> Void in
    UIView.animate(withDuration: yourDuration, animations: { () -> Void in
        // your animation logic here
    })
})

Let me know if this makes sense to you

Michael Fourre
  • 3,005
  • 3
  • 15
  • 26
6

Make use of UIView.animate(withDuration:)'s completion handler. Basic sample below:

func performMyAnimation() {
  UIView.animate(withDuration: {$duration}, 
      animations: { /* Animation Here */ }, 
      completion: { _ in self.performSegue(withIdentifier: "segueIdentifierHere", sender: nil) }
}

Your animation runs in the animations block. Upon completion, you'll then perform the segue to the next screen.


Edit: As the question now includes the animation code, using CABasicAnimation, then perhaps this answer for a CAAnimation callback may work for you.

Basically, you need to wrap your CABasicAnimation call with a CATransaction.

CATransaction.begin()
CATransaction.setCompletionBlock({
    self.performSegue(withIdentifier: "segueIdentifierHere", sender: nil)
})
// Your animation here
CATransaction.commit()
Community
  • 1
  • 1
Josh Hrach
  • 1,238
  • 8
  • 15
  • This makes sense, however when I implement it, there is still no animation, it just segues automatically. – dgelinas21 Feb 07 '17 at 19:37
  • @dgelinas21 I've updated my answer now that you have information on the `CABasicAnimation` usage. Hopefully that helps. – Josh Hrach Feb 08 '17 at 07:38
1

In Swift 4, you would would rewrite the example of @Michael Fourre to:

let yourDelay = 3.0
    let yourDuration = 1.0
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + yourDelay, execute: { () -> Void in
        UIView.animate(withDuration: yourDuration, animations: { () -> Void in
            // your animation logic here
        })
    })
Lukas Mohs
  • 290
  • 3
  • 4