Skip to content

Add GeometryReader#56

Merged
colemancda merged 5 commits into
masterfrom
feature/geometry-reader
Jul 24, 2026
Merged

Add GeometryReader#56
colemancda merged 5 commits into
masterfrom
feature/geometry-reader

Conversation

@colemancda

Copy link
Copy Markdown
Member

GeometryReader { geometry in … }, giving views access to the space they're offered. This was the deepest of the remaining gaps because it's the one place data has to flow backwards: Swift resolves a tree before Compose lays it out, so the node tree had no size-feedback path at all.

How it works, and why it terminates

The interpreter measures, reports the size through a string callback, and the resulting store update re-evaluates with real numbers — so a GeometryReader settles over two passes (zero on the first, measured on the second). No new bridge entry point: the size rides the existing string callback as "<width>,<height>".

Two properties keep that from becoming an infinite layout loop, and both are deliberate:

  1. The reported size comes from the constraints the parent offers, never from the content. If it were content-derived, content sized from the measurement would feed back into it — and since the first pass measures zero, it would deadlock at zero rather than converge.
  2. A report equal to the stored size is dropped, so a steady layout reports once and stops.

An unbounded height (inside a scrolling parent) isn't a real offer, so it reports 0 for that axis rather than infinity; give the reader an explicit .frame(height:) there.

Verification

  • swift test — 89 total passing. One test walks the two-pass settling end to end (content reads w=0 h=0, then w=320 h=240 after a report). The other drives the size store directly to pin the settling rule — a new size re-evaluates, the same size does not, a later change does again, and malformed reports never do. That second test is the one guarding against a re-evaluation loop.
  • Emulator (new "GeometryReader" screen): reports 360 × 200, and bars drawn at size.width / 2 and / 4 measure exactly half and a quarter of the reader — the number is load-bearing, not just displayed. Toggling the frame re-measures in both directions (200 → 320 → 200) and settles each time.

Scope

GeometryProxy exposes size only — frame(in:), safeAreaInsets, and named coordinate spaces aren't modeled, and there's no .coordinateSpace. Worth knowing that a GeometryReader costs an extra evaluation pass whenever its size changes.

@colemancda
colemancda merged commit 8a2596e into master Jul 24, 2026
5 of 6 checks passed
@colemancda
colemancda deleted the feature/geometry-reader branch July 24, 2026 01:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant