Map
Map is a SwiftUI MapKit–backed view (iOS 17+). It renders a map with optional
camera binding, styling, annotations (Marker, MapPolyline, MapPolygon,
MapCircle), and built-in MapKit controls.
The shape of the API mirrors SwiftUI MapKit directly — no Web-style imperative
calls (addMarker(...)). You declare what should appear on the map; the bridge
turns the tree into MapContent.
Basic usage
Use any standard view modifier (frame, padding, aspectRatio, ...) to size the
map. There are no width / height props.
Camera position
Two mutually exclusive ways to set the camera:
The props are named
cameraPosition/initialCameraPositionrather thanposition/initialPositionto avoid clashing with the SwiftUI.position(x:y:)view modifier.
MapCameraPosition is an opaque value (MapCameraPosition class). Construct it
via factories on the MapCameraPosition namespace — never pass a plain dict:
Read what's currently framed via the readonly accessors:
User gestures write the new MapCameraPosition back directly — whatever form
the camera ends up in (typically a region after pan/zoom) is what the observable
will hold.
Map style
pointsOfInterest accepts "all", "excludingAll", or { includes: [...] } /
{ excludes: [...] } with category strings like "airport", "cafe",
"restaurant", etc.
Map content
The following are valid children of <Map>:
Marker
systemImage and monogram are mutually exclusive. tint accepts the same
color strings as the rest of the bridge (system colors, "#RRGGBB",
"rgba(...)", etc.).
MapPolyline
contourStyle is "straight" (default) or "geodesic". The difference is
invisible at short distances and only meaningful for cross-continent routes.
MapPolygon
MapCircle
radius is in meters.
Built-in controls
Use the controls prop and pass either a single control element or a Fragment
containing several:
Valid controls:
MapUserLocationButton— recenter on user location (asks for permission)MapCompass— compass rose that resets rotationMapPitchToggle— toggle 2D / pitched viewMapScaleView— adaptive scale bar
strokeStyle
Used by MapPolyline, MapPolygon, and MapCircle:
cameraBounds — constrain pan / zoom
Pass a MapCameraBounds instance to clamp how far the user can pan and
zoom an interactive map. Two factories:
minimumDistance / maximumDistance are measured in meters from the camera
to its centerCoordinate. Both fields are optional in either factory; pass
the ones you want. MapCameraBounds.distance(...) requires at least one of
them (passing an empty options dict returns null and the prop has no
effect).
The constraint applies to user gestures only — programmatic cameraPosition
writes from JS can still place the camera outside the bounds. MapKit will
typically animate back into bounds on the next user interaction.
Performance tips
- Marker count: a few dozen markers is fine. For hundreds, prefer cluster-like preprocessing in your script and only emit markers visible in the current region.
- Update cadence: each render replays the full content tree. If your script
derives many markers from large arrays on every state change, memoize them
with
useMemo. cameraPositionis two-way: asetValuefrom JS triggers a re-render; the gesture reconciler skips equivalent writes to avoid loops.
