You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This setup is enough to trigger memory churn. Even though items never changes in the viewModel in this example, there's extremely high CPU usage and memory allocations for what should be an idle view.
I did some digging and have a general idea of the root cause. From what I can tell, asking for stateFlow.value inside the state method allocates a new array, every time. I don't know why this happens, perhaps it has something to do with the Kotlin/Swift(ObjC) bridge. You can see this for yourself by adding some simple logging inside of the method:
Accessing `stateFlow.value` is not guaranteed to always return the same instance even when the underlying value is unchanged. This stateFlow behavior was incorrectly causing infinite `objectWillChange` events due to the equality test always reporting `false` even when the new value was, in fact, equal to the previous.
The fix is to go through [`isEqual(to:)`](https://developer.apple.com/documentation/foundation/nsarray/1411770-isequal) to compare the value _contents_ when determine equality before firing off an `objectWillChange` event.
I have a viewModel that exposes a
CStateFlow
ofList
that I'm using in SwiftUI. It looks like this:In my SwiftUI view, I use the
state
helper to subscribe to the stateFlow:This setup is enough to trigger memory churn. Even though
items
never changes in the viewModel in this example, there's extremely high CPU usage and memory allocations for what should be an idle view.I did some digging and have a general idea of the root cause. From what I can tell, asking for
stateFlow.value
inside thestate
method allocates a new array, every time. I don't know why this happens, perhaps it has something to do with the Kotlin/Swift(ObjC) bridge. You can see this for yourself by adding some simple logging inside of the method:This will output, in an infinite loop, something like this:
The solution is to change the equality test of
NSArray
state
helper at https://github.com/icerockdev/moko-mvvm/blob/develop/mvvm-flow/apple/xcode/mokoMvvmFlowSwiftUI/ViewModelState.swift#L86.Rather than
equals: { $0 === $1 },
it should useisEqual(to:)
to compare array contents,equals: { $0!.isEqual(to: $1 as! Array<T>) },
After making this change locally, the memory churn goes away.
The text was updated successfully, but these errors were encountered: