Reputation: 269
I'm wondering how it is possible to chain a sequence of UIView.animationWithDuration:completion:
functions to perform each next function from completion closure of previous animationWithDuration. So I should have something like:
finalAnimation <<< animationB <<< animationA <<< initialValues()
It's easy to chain them if functions doesn't have any time delay inside. Also it's easy to build a queue of animations with a shared object that contains queue items. But it's not clear how to build such queue without sharing anything but just chaining animationWithDuration:completion:
Thanks for your advice
Upvotes: 2
Views: 664
Reputation: 131418
I agree with @NRitH that keyframe animations are a good way to go.
Another option is to write a method that calls itself from the completion handler. Something like this:
var step = 3;
func animate()
{
UIView.animateWithDuration: 1.0,
delay: 1.0,
options: 0,
animations: ^
{
switch step:
{
case 3:
//1st animation
case 2:
//2nd animation
case 1:
//3rd animation
default:
//we're done
}
},
completion: ^
{
(finished) in
step--
if finished && step > 0
{
animate()
}
}
}
(Syntax may not be perfect. I've been working in Objective-C for the past month or so so my Swift has gotten a tad rusty.)
I just realized that you wanted to add delay between the animations. I edited my code to show how to do that.
I put in a fixed delay of 1 second between steps. If you want variable delay, you'd need to create an array of delay values.
Upvotes: 1
Reputation: 4919
You can not chain with animation, chaining requires the function to return optional type fun1()?.func2()?.func3()
. This is not achievable since animateWithDuraion: return immediately. You can use dispatch_semaphore to wait for completion block but it is not recommended since your animation should not not block the main thread
here is my suggestion:
you can do something like this
func myAnimation(duration: NSTimeInterval, animation:() -> Void, onFinish: () -> Void) {
UIView.animateWithDuration(duration, animations: { () -> Void in
animation()
}) { (finished: Bool) -> Void in
onFinish()
}
}
and then
myAnimation(0.0, { animation in
}) { completion in
myAnimation(0.0, { animation in
}, { completion in
myAnimation(0.0, { animation in
}, { completion in
})
})
}
Upvotes: 1
Reputation: 13893
DON'T nest animations. What you want is animateKeyframesWithDuration(_:delay:options:animations:completion:), which allows you to chain animations together in a much cleaner way.
See also http://commandshift.co.uk/blog/2014/04/01/stop-nesting-animation-blocks/
Upvotes: 1
Reputation: 237
I came across this library which might be interesting for you. It has a section in its documentation about chaining animations.
https://github.com/MengTo/Spring
Upvotes: 1