fix(ios): include the resolved style in VoltraElement identity - #274
Open
rlods wants to merge 2 commits into
Open
fix(ios): include the resolved style in VoltraElement identity#274rlods wants to merge 2 commits into
rlods wants to merge 2 commits into
Conversation
`_props` carries only the stylesheet index of a deduplicated style, so two payloads pointing at different styles compared equal and SwiftUI's Equatable fast path skipped the re-render, leaving the old style on screen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
rlods
marked this pull request as ready for review
September 10, 2026 23:10
Author
|
@V3RON 👋 here is an other fix I applied it as a patch in my project and I confirm it resolves the described issue |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
On iOS, a payload that only changes a deduplicated style leaves the previous style on screen.
renderWidgetToStringhoists every style object into a shared stylesheet (s) and leaves the element referencing it by index.VoltraElementisHashable, and its==comparestype,id,childrenand_props— where_propsholds only that index, not the style it points at. Two payloads whose element serializes identically but whose stylesheet entry differs therefore compare equal.VoltraNodeis an EquatableView, so SwiftUI takes its fast path, skips re-evaluating the node, and keeps whatever it rendered last time.Reproduction
Schedule a two-entry widget timeline in which a
Textkeeps its content and only its colour changes. The secondTextis the control: its content does change, which proves the timeline advanced.Both entries serialize the number to the exact same node,
{"t":0,"c":"42","p":{"s":0}}, and differ only inside the stylesheet:After a minute the label flips to
B grey, so the entry did change — but the42stays orange. Expected: it turns grey.This is not limited to the toy case. It shows up wherever a style is deduplicated and only its contents change: a status widget that recolors an unchanged counter at a date boundary picks up the new background and the new caption, while the counter keeps its old colour, because the surrounding elements changed and it did not.
Fix
VoltraElementidentity now includes the resolvedstyle— the existing computed property that follows the stylesheet index — in both==andhash(into:). Nested elements are covered by recursion throughchildren.This makes equality strictly finer, so nodes that used to be skipped are re-evaluated. Nothing changes for payloads that ship inline styles, or that never reuse an index across renders.
Testing
swiftformat --lint ios: clean (0/163 files require formatting).swift test: 146 tests pass.shared/+ui/type-check against the iOS 17 simulator SDK.42before the fix, grey42after.No unit test in this PR:
VoltraElement.swiftandVoltraNode.swiftare excluded from theVoltraSharedCoreSPM target (VoltraNodeconforms toViewand dispatches into theuilayer), so no target inPackage.swiftcan construct aVoltraElement. Happy to add one if you'd like the JSON→AST types split into a testable target.Checklist
npm test)npm run lint:libOnly)npm run format:check)🤖 Generated with Claude Code