GeometryReader hands you the size and frame of the space it occupies, at the cost of eating
that space. Avoid it where you can; where you need it, contain it so it cannot distort the
layout around it.
What the Proxy Gives You
The ViewBuilder closure receives a GeometryProxy with size, safeAreaInsets, and a
frame(in:) function that converts the reader's frame into a coordinate space, including
custom spaces declared with the coordinateSpace modifier.
GeometryReader { geometry in
Text("Hello!")
.frame(
width: geometry.size.width,
height: geometry.size.height
)
}
GeometryReader places its children in the top left corner, not the center. That alone
surprises most first uses; position the content yourself.
Containing It
GeometryReader expands to fill all the available space. Three ways to keep that greed from
wrecking the layout:
- Full-screen use is fine as is; the reader wants all the space and you want it to have it.
- Otherwise, cap it with
frameoraspectRatioso it only takes the space you assign. - Best: put the reader inside a
backgroundoroverlayof the view you want to measure. SwiftUI sizes background and overlay views to their host, so the reader reports the host's size without claiming any layout space of its own.
SomeView()
.background(
GeometryReader { geometry in
Color.clear.preference(
key: SizePreferenceKey.self,
value: geometry.size
)
}
)
When to Skip It
For drawing, use the Shape API instead. Shape.path(in rect: CGRect) already receives the
available space, so a chart or custom shape needs no GeometryReader at all.