Wind your way through advanced animations in SwiftUI

RSS for tag

Discuss the WWDC23 Session Wind your way through advanced animations in SwiftUI

View Session

Posts under wwdc2023-10157 tag

3 Posts
Sort by:
Post not yet marked as solved
6 Replies
561 Views
Hi I'm trying to use the new PhaseAnimator from iOS 17 and I noticed a bug. For some reason, the animation is not deallocated when the view is removed from hierarchy, leading to a crash app. Example enum OuterBreathState: CaseIterable { case exhale, inhale var scale: CGFloat { switch self { case .inhale: return 2 case .exhale: return 1 } } var color: Color { switch self { case .inhale: return .white case .exhale: return .blue } } } struct PhaseView: View { var body: some View { PhaseAnimator(OuterBreathState.allCases) { state in Circle() .background(.clear) .frame(width: 150, height: 150) .padding(.vertical) .scaleEffect(state.scale) .background(in: Circle()) .foregroundStyle(state.color) } animation: {state in switch state { case .inhale: return .easeInOut(duration: 1.5) case .exhale: return .easeInOut(duration: 3.5) } } } } struct ContentView: View { var body: some View { NavigationStack { NavigationLink("push") { PhaseView() } } } } Pushing the view works just fine, but after popping, the app becomes unresponsive 😓 It's the content update that fails actually. If I make no updates to the Circle, everything works fine. I also tried with the phaseAnimator trailing function, I get the same behaviour. Interesting fact : if I use a trigger (and even a timer that flips that trigger to mimic the infinite loop), it does not crash the app. Here is the code enum OuterBreathState: CaseIterable { case exhale, inhale var scale: CGFloat { switch self { case .inhale: return 2 case .exhale: return 1 } } var color: Color { switch self { case .inhale: return .white case .exhale: return .blue } } } struct PhaseView: View { @State var animate = false let timer = Timer.publish(every: 5, tolerance: .zero, on: .main, in: .default).autoconnect() var body: some View { PhaseAnimator(OuterBreathState.allCases, trigger: animate) { state in Circle() .background(.clear) .frame(width: 150, height: 150) .padding(.vertical) .scaleEffect(state.scale) .background(in: Circle()) .foregroundStyle(state.color) } animation: {state in switch state { case .inhale: return .easeInOut(duration: 1.5) case .exhale: return .easeInOut(duration: 3.5) } } .onReceive(timer, perform: { _ in animate.toggle() }) .onTapGesture { animate.toggle() } } } struct ContentView: View { var body: some View { NavigationStack { NavigationLink("push") { PhaseView() } } } } #Preview { ContentView() } Any idea why it crashes and how I can make it work ? Thanks!
Posted
by radada.
Last updated
.
Post not yet marked as solved
0 Replies
237 Views
I watched both sessions. At the end of the keyframe animations session, the presenter at 16:42 shows the KeyFrameTimeline and its API. // Keyframes let myKeyframes = KeyframeTimeline(initialValue: CGPoint.zero) { KeyframeTrack(\.x) {...} KeyframeTrack(\.y) {...} } // Duration in seconds let duration: TimeInterval = myKeyframes.duration // Value for time let value = myKeyframes.value (time: 1.2) Then he says that he used this to draw the charts seen earlier in the WWDC sessions. I thought that he used the instance of a KeyFrameTimeline directly in Chart() to make a graph of the variables and values over time. If trying to to it I get the error message that KeyFrameTimeline needs to conform to Random Access Collection. So maybe I am missing something? I am curious to see how that would work! And how to make a graph for each KeyframeTrack inside my KeyframeTimeline
Posted Last updated
.
Post not yet marked as solved
0 Replies
340 Views
Hi, When defining a KeyFrameAnimation with spring tracks, the animation do not complete until the very end , but, as default when using withAnimation with a spring animation, it will start the next animation For example if a complete spring animation is 600ms, the next animation may start only after 300ms My designer has given me the mass, stiffness, and dumping values for the animation, and expects that the animation will perform for X time, and after that a new animation will start, as it occurs on figma Using withAnimation with completition callback i can replicate the behaviour, using the ".removed" CompletitionCriteria, but i'd rather use the new KeyFrame phase animator, because i'm not very confident having 5-6 animations started recursively with "withAnimation"
Posted
by Playrom.
Last updated
.