Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Swift Animation does not work when reentering screen

I have built a view with an animation and everything seemed to work fine, but then I found out that it only works for the first time and not for the second. As I am a newbie in Swift programming I don’t have an idea where the problem is. I viewed different tutorials for animations and all worked the same way as I have implemented it. I wrote a small sample to reproduce the issue:

import SwiftUI

struct BugSample: View {
    var body: some View {
        TabView {
            ContentView()
                .tabItem {
                    Label("BUG", systemImage: "checkmark")
                }
        }
    }
}

struct Person: Identifiable, Hashable {
    var id: UUID
    var name: String
    
    init(id: UUID = UUID(), name: String) {
        self.id = id
        self.name = name
    }
}

struct ContentView: View {
    @State private var selectedPerson: Person?
    
    var body: some View {
        NavigationSplitView {
            PersonsListView(selectedPerson: $selectedPerson)
        } detail: {
            if let selectedPerson {
                GalleryView()
            } else {
                Text("Should not reach here")
            }
        }
    }
}

struct PersonsListView: View {
    @Binding var selectedPerson: Person?
    
    var data = [Person(name: "A"), Person(name: "B"), Person(name: "C")]
    
    var body: some View {
        List(data, selection: $selectedPerson) { entry in
            Text(entry.name)
                .onTapGesture {
                    selectedPerson = entry
                }
                .listRowSeparator(.hidden)
        }
    }
}

struct GalleryView: View {
    var body: some View {
        NavigationStack {
            VStack(spacing: 20) {
                ProgressView()
                CircularView()
            }
        }
    }
}

struct CircularView: View {
    @State var scale = 1.0

    var body: some View {
        Circle()
            .frame(width: 200, height: 200)
            .scaleEffect(scale)
            .onAppear {
                let baseAnimation = Animation.easeInOut(duration: 1)
                let repeated = baseAnimation.repeatForever(autoreverses: true)

                withAnimation(repeated) {
                    scale = 0.5
                }
            }
    }
}

When you click on one of the 3 entries, then the circle will animate correctly and when I go back and open the screen again, it won’t work. I have added also a ProgressView to check if this works and it is spinning around, so maybe the issue lies within the code.
My first suggestion was the NavigationSplitView because I have seen that there is an issue with a missing animation, but it is different to my issue (https://forums.developer.apple.com/forums/thread/728132).
Has anyone an idea for that problem, I tried several ways the last hours but I don’t find a way to get the animation work again.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

For some reason, .onAppear (and also onDisappear, when present) are being called, but the animation doesn’t restart the second time.

To fix, trigger the animation using task instead:

Circle()
    .frame(width: 200, height: 200)
    .scaleEffect(scale)
    .task { @MainActor in
        let baseAnimation = Animation.easeInOut(duration: 1)
        let repeated = baseAnimation.repeatForever(autoreverses: true)

        withAnimation(repeated) {
            scale = 0.5
        }
    }
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading