I don't like having the parent view passing in a binding to a @State var it owns, just so to kick start something to happen inside the child view. It seems wrong to me. So here is what I end up:
import SwiftUI
struct BarView: View {
struct Foo: View {
class Notifier: ObservableObject {
@Published var counter = 0
}
@ObservedObject private var notifier = Notifier()
@State private var animationFlag = false
static private let animationDuration = 0.5
// trigger some action when this is called
func doFoo() {
notifier.counter = 1
}
var body: some View {
VStack {
ZStack {
Text(verbatim: "🤔").font(.system(size: 150))
.scaleEffect(animationFlag ? 1.2 : 1)
.animation(Animation.linear(duration: Self.animationDuration))
}
.frame(width: 200, height: 200)
Text(verbatim: "self.flag = \(self.animationFlag)")
}
.onReceive(notifier.objectWillChange) { _ in
self.animationFlag = true
DispatchQueue.main.asyncAfter(deadline: .now() + Self.animationDuration) {
self.animationFlag = false
}
}
}
}
let foo = Foo() // seems okay to do this way?
var body: some View {
VStack {
foo
Spacer()
Button("Action!...") {
self.foo.doFoo()
}
}
}
}
struct ConfuseMe_Previews: PreviewProvider {
static var previews: some View {
BarView()
}
}
So it's back to how I wanted originally. But instead use an @ObservedObject to indirectly cause the internal @State var change.
I wonder, the way I originally try to change the @State var, which is wrong, why SwiftUI does not catch it and print some error message...