Record being wrong about which change broke a test
A UI test went red in the same run that adopted three new APIs. The one touching that screen was reverted; the test still failed. A modifier order was corrected; still failed. Simulator data was wiped; still failed. Running it against a clean checkout — which should have been the first move, not the fourth — it failed there too, with none of the work present. The scrolling entry had already been rewritten to explain the fault in confident detail. That write-up was fiction, so it now says what actually happened: the API was convicted on circumstance and remains unproven here, and the one claim that survives is about its two-way binding costing invalidations. xcode-practice gets the general lesson, since it will outlive this particular test: stash and rerun before reasoning about which edit did it, and a note recording a false cause is worse than no note, because the next person believes it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
f5a3d932fa
commit
542dd925d0
4 files changed
+46
-5
No files matched your search
@@ -25,9 +25,29 @@ following the offset while the user drags.
|
||||
to reach `proxy.scrollTo` from a `.task`. In our card list that is the
|
||||
filter chip strip, which scrolls the active chip into view.
|
||||
|
||||
**Step forward?** Modest but real. One layer of nesting disappears and the
|
||||
scroll position stops being write-only. Not urgent — the existing code
|
||||
works — so worth doing when that view is touched for another reason.
|
||||
**Step forward? Unproven — we backed it out.** Swapping `ScrollViewReader`
|
||||
for `.scrollPosition(id:)` coincided with the UI test for that strip
|
||||
failing, so it looked like the culprit and was reverted. It was not:
|
||||
the same test fails on a completely clean tree, with none of the change
|
||||
present. Something in the environment broke that test, and the swap was
|
||||
convicted on circumstance.
|
||||
|
||||
The revert stands anyway, because it was never worth much here — this
|
||||
strip only ever *writes* a scroll target, which is exactly what the proxy
|
||||
already does. But the reasoning above is worth keeping, because being
|
||||
wrong about it taught the real lesson: **when a change and a failure
|
||||
arrive together, check the failure against an unchanged tree before
|
||||
concluding.** Two rounds of edits went into explaining a fault that was
|
||||
not there.
|
||||
|
||||
One thing that does hold, independent of all that:
|
||||
|
||||
- **`scrollPosition` is two-way, so it costs invalidations.** It writes to
|
||||
its binding on every scroll, where the proxy only takes commands. It
|
||||
therefore belongs in a small view. Ours would have sat in a screen whose
|
||||
body derives a sorted, grouped card list — every drag of the strip would
|
||||
have recomputed all of it. Extracting the strip into its own view was
|
||||
worth keeping regardless of which scrolling API ends up inside it.
|
||||
|
||||
**Available since.** iOS 17, so nothing blocks it at our deployment
|
||||
target. `onScrollGeometryChange` needs iOS 18.
|
||||
|
||||
Reference in new issue
Block a user