I am unable to use the EquatableView as per the article: Link1 and link2. I expected the "==" function in the TestView to be invoked every time I click on the Button.
Am I missing something here?
struct ContentView: View {
@State var state = false
var body: some View {
VStack {
EquatableView(content: TestView(state: $state))
Button("Change state", action: {state.toggle()})
}
}
}
struct TestView: View, Equatable {
@Binding var state: Bool
var body: some View {
let _ = print("Test updated")
Text("TestView state : (state.description)")
}
static func == (lhs: TestView, rhs: TestView) -> Bool {
//Never printed or invoked
let _ = print ("lhs == rhs invoked (lhs.state) == (rhs.state)")
return lhs.state == rhs.state
}
}
UPDATE:
After very helpful response from Alperen, it shows that “@State” has to be added for == to be triggered. However, passing a "@State" var from parent directly to SubView’s "@State" for the same var, as suggested below, makes no sense.
So, I added another variable to TestView “@State var notUsed“ which will not work unless "@Binding" is removed. One would also want to compare "@Binding" vars, so to me this is illogical.
My question still remains, am I missing something or is this behaviour by design?
2
Answers
That code is working. Can you try this?
Equatable
is used when a view is created, so either it should replace already existed or not. In your exampleTestView
is not re-created, because it should not on binding changed – onlybody
rendered with new value.To simulate recreation (for testing purpose) the simplest it to add condition. Equatibility is just a optimisation technic it helps SwiftUI to detect replace existed view instance or not.
Here is updated example to demo Equatable works. Tested with Xcode 12.1 / iOS 14.1