How can I animate changes to an @ObservedObject?
It looks as though using withAnimation
inside an async closure causes the color not to animate, but instead to change instantly.
Either removing the wrapping asyncAfter
, or removing the withAnimation
call and adding an animation
modifier in the body
of your ContentView
(as follows) should fix the issue:
Color(viewModel.color).onAppear {
self.viewModel.change()
}.animation(.easeInOut(duration: 1))
Tested locally (iOS 13.3, Xcode 11.3) and this also appears to dissolve/fade from blue to red as you intend.
How to use WithAnimation with @ObservedObject
You can specify the animation directly inside withAnimation
. This way it will be specific for this change only:
Button(action: {
withAnimation(.easeInOut) { // add animation
self.model.logout()
}
}) {
Text("Sign Out")
}
SwiftUI Animation from @Published property changing from outside the View
The easiest option is to add a withAnimation
block inside your timer closure:
withAnimation(.easeIn(duration: 0.5)) {
isOn.toggle()
}
If you don't have the ability to change the @ObservableObject closure, you could add a local variable to mirror the changes:
struct ContentView: View {
@ObservedObject var model: Model
@State var localIsOn = false
var body: some View {
VStack {
if localIsOn {
MyImage(color: .blue)
} else {
MyImage(color: .clear)
}
Spacer()
Toggle("switch", isOn: $model.isOn.animation(.easeIn(duration: 0.5)))
Spacer()
}.onChange(of: model.isOn) { (on) in
withAnimation {
localIsOn = on
}
}
}
}
You could also do a similar trick with a mirrored variable inside your ObservableObject:
struct ContentView: View {
@ObservedObject var model: Model
var body: some View {
VStack {
if model.animatedOn {
MyImage(color: .blue)
} else {
MyImage(color: .clear)
}
Spacer()
Toggle("switch", isOn: $model.isOn.animation(.easeIn(duration: 0.5)))
Spacer()
}
}
}
class Model: ObservableObject {
@Published var isOn: Bool = false
@Published var animatedOn : Bool = false
var cancellable : AnyCancellable?
var timer = Timer()
init() {
timer = Timer.scheduledTimer(withTimeInterval: 5, repeats: true, block: { [unowned self] _ in
isOn.toggle()
})
cancellable = $isOn.sink(receiveValue: { (on) in
withAnimation {
self.animatedOn = on
}
})
}
}
In SwiftUI how can I animate a Published View change?
Moving your view initialization to MasterView makes everything easier:
struct MasterView: View {
@State var playerLeft: Bool = false
@ObservedObject var viewModel: MasterViewModel
var body: some View {
ZStack {
VStack { //this represents WaitPlayerBackView
if viewModel.day { //here are the posibles views that self.viewModel.currentView could have
Text("DayView").transition(AnyTransition.opacity.animation(.easeInOut(duration: 1.0)))
} else {
Text("NightView").transition(AnyTransition.opacity.animation(.(duration: 1.0)))
}
}
}
}
}
class MasterViewModel: ObservableObject {
@Published var day: Bool = false
init () {
_ = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(changeView), userInfo: nil, repeats: true) //Only for testing
}
@objc func changeView() { //@objc is only for testing
day.toggle()
}
}
How to animate the removal of a view created with a ForEach loop getting its data from an ObservableObject in SwiftUI
It is not clear which effect do you try to achieve, but on remove you should animate not view internals, but view itself, ie. in parent, because view remove there and as-a-whole.
Something like (just direction where to experiment):
var body: some View {
ZStack {
ForEach(tagModel.tags, id: \.self) { label in
TagView(label: label)
.transition(.move(edge: .leading)) // << here !! (maybe asymmetric needed)
}
.onReceive(timer) { _ in
self.tagModel.addNextTag()
if tagModel.tags.count > 3 {
self.tagModel.removeOldestTag()
}
}
}
.animation(Animation.easeInOut(duration: 1)) // << here !! (parent animates subview removing)
Related Topics
Scenekit Won't Scale a Dynamic Body
Xcode Error - Undefined Symbols for Architecture X86_64
Why Does Type(Of:) Return Metatype, Rather Than T.Type
Swiftui 2 Pop to Root View with No Scene Delegate
Implicitlyunwrappedoptional in Init VS Later
Swift Pattern Matching with Enum and Optional Tuple Associated Values
How to Get Data from a Swift Nsurlsession
How to Simplify Swift Enum Custom Init
How to Test an Optionset with a Switch Statement
How to Blur the Background in a Swiftui MACos Application
Callback Url Not Approved Despite Being Provided Twitter API
Shared Cookies with Wkprocesspool for Wkwebview in Swift
Swift Packages and Conflicting Dependencies
Firebase Sms Verification on iOS - 'Token Mismatch'