Hi, I'd like to know whether it's possible to override the diffing? I'm hitting some performance bottlenecks because my view is re-rendering but I'm not sure what's the right protocol here. In plain views EquatableView
/ Equatable
should do the trick. In views that use a viewStore
I suspect this could work differently?
Default initialiser for WithViewStore
accepts removeDuplicates:
. You can read more in documentation here.
Isn't it better to use SwiftUI EquatableView
instead of the removeDuplicates
? I can see how the state comparison works just fine but what if SwiftUI has performance optimizations for EquatableView
?
AFAICT, the real usefulness of EquatableView
lies in being able to define your own equality logic where view equality can't be determined based purely on the state's raw value alone. To take a contrived example, imagine a view that has a counter that renders a Circle
in a different color based on whether or not the counter is odd or event:
struct CircleView: View {
var store: Store<CounterState, Void> // CounterState == Int
var body: some View {
WithViewStore(store) { viewStore in
Circle().backgroundColor(
(viewStore.state % 2 == 0) ? Color.red : Color.green
)
}
}
}
Even though this view is carefully scoped to only the state it cares about, it will still re-evaluate the WithViewStore
body every time the counter value changes - ideally the view should only re-evaluate if the counter's even-ness changes which we can't determine purely by ==
alone.
Now if this was a pure SwiftUI implementation and you were using @State
then the only way you have of refining this behaviour is to make your view Equatable
and define a custom ==
function for the view that compares the even-ness of the state.
In this case though the state changes are being driven by the ViewStore
which allows you to define your own removeDuplicates:
as @eimantas mentioned so you could instead just pass in a custom implementation that removed duplicates based on even-ness of the state and the contents of the WithViewStore
body will only be re-calculated when that changes.
If there's any optimisations in SwiftUI its more likely to be in the rendering pass rather than the body calculation phase. Even if your view body is re-calculated I think SwiftUI is generally smart enough not to re-render it if the resulting view body is unchanged, but avoiding unnecessary body re-evaluations is just another layer of optimisation you can achieve by carefully scoping your view state and I think either a custom removeDuplicates
implementation of using an equatable view would have the same effect.
a custom
removeDuplicates
implementation of using an equatable view would have the same effect.
I don't think that's true. I have this ItemCell I use in lazy grid view or lazy hstack.
Without Equatable:
With Equatable:
Using Equatable seems to make a huge difference.
@mbrandonw can you provide some guidance on this?