title: MapUtils
description: Synchronous geometry helpers for MapKit coordinate / region types: distance(a, b) (Haversine, meters), bearing(a, b) (degrees), regionContains(region, coordinate), regionFromCoordinates(coords, paddingFactor?). Pure functions, safe during render.
MapUtils is a small set of synchronous geometry helpers for the MapKit
coordinate / region types from the views layer. Pure functions, safe to call
during render or in tight loops.
distance(a, b)
Great-circle distance between two MapCoordinates in meters, computed via
the Haversine formula using mean Earth radius (6_371_008.8 m).
Accuracy is good enough for typical "near me / how far away" use cases. For applications that need geodetic-grade precision (geological surveying etc.), use a dedicated geodesy library.
bearing(a, b)
Initial bearing (forward azimuth) from a to b, in degrees normalized to
[0, 360):
The bearing returned is the initial bearing — on long great-circle routes the actual direction at the destination is different. For map-marker rotation the initial bearing is what you want.
regionContains(region, coordinate)
Whether coordinate lies inside the rectangular MapRegion:
Caveat: does not handle regions that straddle the ±180° antimeridian (the "Pacific date line"). If you need cross-meridian membership, split the test into two regions manually.
regionFromCoordinates(coordinates, paddingFactor?)
Smallest MapRegion enclosing all coordinates. Useful for fitting the camera
around a set of Markers or a polyline.
Edge cases:
- Empty array → returns
null. - Single coordinate → returns a region with a minimal 0.01° span centered on that point.
- Coordinates collinear in latitude or longitude → span is clamped to a
minimum of
0.005°to avoid0span (which MapKit would reject). - Antimeridian-crossing input (e.g. one point at
+170°, one at-170°) produces a region spanning the long way around. Not Phase-3a–supported.
formatDistance(meters, options?)
Localized human-readable distance via Apple's MKDistanceFormatter. Negative
inputs clamp to 0.
Output is locale-aware — do not assert on exact strings in tests.
formatDuration(seconds, options?)
Localized duration via DateComponentsFormatter. Negative inputs return an
empty string.
When to use
- After
MapSearch.locate/Location.geocodeAddress:regionFromCoordinateslets you auto-fit the camera around all hits. - "Within Xm of me": call
distance(myLocation, item.coordinate) < X. - Sorting search results by proximity: stable-sort the array by
distance. - Compass arrow on a marker pointing to a target:
bearinggives the rotation in degrees. - Rendering route metadata (
route.distance/route.expectedTravelTimefromMapDirections):formatDistance/formatDurationgive locale-aware labels.
