SwiftUI offers .animation()
on bindings that will animate changes in the view. But if an @Published
property from an @ObserveredObject
changes 'autonomously' (e.g., from a timer), while the view will update in response to the change, there is no obvious way to get the view to animate the change.
In the example below, when isOn
is changed from the Toggle, it animates, but when changed from the Timer
it does not. Interestingly, if I use a ternary conditional here rather than if
/else
even the toggle will not trigger animation.
struct ContentView: View {
@ObservedObject var model: Model
var body: some View {
VStack {
if model.isOn {
MyImage(color: .blue)
} else {
MyImage(color: .clear)
}
Spacer()
Toggle("switch", isOn: $model.isOn.animation(.easeIn(duration: 0.5)))
Spacer()
}
}
}
struct MyImage: View {
var color: Color
var body: some View {
Image(systemName: "pencil.circle.fill")
.resizable()
.frame(width: 100, height: 100)
.foregroundColor(color)
}
}
class Model: ObservableObject {
@Published var isOn: Bool = false
var timer = Timer()
init() {
timer = Timer.scheduledTimer(withTimeInterval: 5, repeats: true, block: { [unowned self] _ in
isOn.toggle()
})
}
}
How can I trigger animations when the value changes are not coming from a binding?