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.
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
}
}