Add SwiftUI observation mount tests#112
Conversation
|
I just upgraded the test to validate that Observations 'withObservationTracking' call will properly observe the state changes. |
|
I've added the companion PR's for this. Lets try to keep discussion centered here for the most part. Getting this compiling with the skipstone changes was a bit of a challenge, but I think it's working when I point at local repos. skiptools/skipstone#251 This makes each View insert a withObservationTracking to drive invalidation. We need to be careful to only read the View body in the withObservationTracking closure. We can then convert it to the java Object. I have a small runtime exploration here that I've been using. At this point, the views are re-rendering, but I'm seeing that the Views are still getting invalidated to often. In the second example, both views are re-rendering, but in SwiftUI, only one renders at a time. |
|
So this commit opts the top level skip.ui View into Renderable. This keeps it from flattening it's children when the parent calls This should prevent Skip from over rendering, but it may have some larger impacts. On a positive note, this seems to work! Screen.Recording.2026-05-21.at.3.28.03.PM.mov |
This is the first small slice towards achieving true Observation support for skip-ui
The issue isn't that it's unavailable, but there's a gap in the Skip bridge path to trigger recomposition.
That works for app-level
@Observablemodels that canimport SkipFuse, but it does not cover third-party libraries that manually implementObservablewithObservationRegistrar/ mutation notifications and do not want to depend on SkipI'll try to make the commits structured in a way where we can discuss it at the different steps.
This PR does not try to solve the problem yet. It only adds a minimal mounted-runtime test:
This first commit just exposes the problem to testing.
If I create an object that conforms to Observable, but doesn't apply the macro, it does not observe the changes on the type.
The test sets up a harness to check rendering changes. The important part is that this is not a fresh Swift read after mutation. It checks whether Skip/Compose receives the Observation invalidation and recomposes.
Current behavior:
skip testbuilds the project, mounts the test view, and confirms the initial render. The failure happens only after mutating the observed value:These do pass with the similar SwiftUI only harness.
swift testI used an LLM to help me get the harness into place. Runtime code will be written by hand
Relevant context:
@Observablesupport: https://skip.dev/docs/app-development/#observables