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?
Equatable
is used when a view is created, so either it should replace already existed or not. In your example TestView
is not re-created, because it should not on binding changed - only body
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
struct ContentView: View {
@State var state = false
var body: some View {
VStack {
if state {
EquatableView(content: TestView(state: $state))
}
Button("Change state", action: {state.toggle()})
}
}
}
struct TestView: View, Equatable {
@Binding var state: Bool
init(state: Binding<Bool>) {
_state = state
print(">> inited") // << check if created
}
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
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With