Open jeffc-dev opened 2 months ago
Thanks for the detailed report!I believe I know why this might happen. I’ll investigate later today and give you a fix or status report.
Status: I don't have a fix for this, but just by looking at it I can tell why it's likely happening, and that will let you understand how to avoid it.
Both SwiftUI and Compose may re-evaluate view bodies due to state, environment, etc changes. And view bodies typically create child views. So in sum you have a lot of cases where views get recreated.
@State values are preserved across recreation. But non-@State values are not. So what I believe is happening is:
Why does it work in SwiftUI? I'm actually not sure if it would work correctly across all cases, but SwiftUI seems to be better at avoiding re-renders and also better at copying views without re-running their initializations (i.e. taking advantage of struct value semantics).
I'm not sure what your real use case is, so I hesitate to prescribe a solution. But for example a static UUID set or a @State or a value from a shared ViewModel would work. The problem is in using a value that is reset along with view construction.
Please let me know if this makes sense.
I ran across a weird issue wherein setting a
@State
variable from within.task
based on an array of values (I tested with UUIDs and random Ints) works properly in SwiftUI but not Compose.In a nutshell, assume that a view struct has the following variables:
This initializes the view with 5 random UUIDs and a
firstUUID
@State
variable set tonil
.Within the view's
.task
, I attempt to setfirstUUID
to the first UUID in the array.This works properly within SwiftUI, but not Compose.
(Real-world context: I want to use UUIDs to model different pieces of model that a user can toggle between in the view...)
I do note, however, that (assuming these views are in tabs) if I click on a different tab and then return the value is set properly in Compose as well. It also seems to work consistently within the second tab. Some sort of timing issue, perhaps?
I tried this using random Ints and saw the same behavior with them, so I don't think it's specific to UUID, per se.
This has been a bit hard to explain, so I've created a test project that I believe demonstrates what I'm seeing. I will attach a screenshot of the output from Compose (left) and SwiftUI (right), respectively.
You'll see that Compose consistently identifies the first UUID in the array within view reconstruction, but comes up with a completely different UUID when it's based on the
@State
variable.This might seem a bit esoteric, but I found it while having trouble getting a struct to conform to
Identifiable
(hence the UUID - I was using one for my struct'sid
). I imagine others will run across this as well.