Phase Animations
Phase animations allow you to animate through multiple phases. And under the hood, it just uses regular animations and their completion handlers. So here's a wiggle example where we wiggle a view twice when clicked. We can also build this wiggle with keyframe animations or an Animatable modifier.
struct Wiggle: View { @State private var trigger = 0 let angles: [Double] = [ 0, -15, 12, -8, 4 ] var body: some View { RoundedRectangle(cornerRadius: 12) .fill(.red) .frame(width: 80, height: 96) .onTapGesture { trigger += 1 } .phaseAnimator(Array(angles.indices), trigger: trigger) { button, phase in button .rotationEffect(.degrees( angles[phase] )) } animation: { phase in .easeInOut( duration: phase < 2 ? 0.1 : 0.15 ) } }}
Drag points vertically to change values. Up and Down arrow keys edit a selected value; hold Shift for larger steps.
6 points.Gotchas
Here's another example where we try to move up, wait, and move down. And we try to do the waiting by inserting the same phase twice. This does not animate as expected. And the reason is that when we animate from -100 to -100, the animation completes immediately because there is nothing to animate and then continues with the next animation (back to the starting value). If we want to add a delay, we need to modify the animation curve itself. We can use the delay toggle to see that effect.
struct MoveAndWait: View { @State private var trigger = 0 var body: some View { RoundedRectangle(cornerRadius: 8) .fill(.red) .frame(width: 48, height: 48) .onTapGesture { trigger += 1 } .phaseAnimator([ 0.0, -100, -100 ], trigger: trigger) { content, offset in content .offset(y: offset) } animation: { offset in .easeInOut(duration: 0.5) } }}
Resources

Phase Animator Behavior, on skipped phases and adding a delay.
https://chris.eidhof.nl/post/phase-animator/
Four Ways to Shake compares phase animations, keyframes, and their timing curves.
https://chris.eidhof.nl/post/four-ways-to-shake/
Swift Talk #402, Wobble Animation: a wiggle effect using a phase animator and the Animatable API.
https://talk.objc.io/episodes/S01E402-wobble-animation
Apple's Wind your way through advanced animations in SwiftUI (WWDC23). Animation phases start at 2:23.
https://developer.apple.com/videos/play/wwdc2023/10157/?time=143
Thinking in SwiftUI, Animations chapter: “Phase-Based Animations.”
https://www.objc.io/books/thinking-in-swiftui/
Apple's Controlling the timing and movements of your animations.
https://developer.apple.com/documentation/swiftui/controlling-the-timing-and-movements-of-your-animations
Natalia Panferova's Creating multi-step animations with PhaseAnimator in SwiftUI goes into way more detail on the full API of phase-based animations.
https://nilcoalescing.com/blog/PhaseAnimationsInSwiftUI/