Skip to content

Add GeocodingProvider for forward and reverse geocoding - #26

Open
gurmeherchawla wants to merge 3 commits into
skiptools:mainfrom
Clockworks-Solutions:feature/geocode
Open

gurmeherchawla wants to merge 3 commits into
skiptools:mainfrom
Clockworks-Solutions:feature/geocode

Conversation

@gurmeherchawla

Copy link
Copy Markdown

Summary

Adds GeocodingProvider, which converts between coordinates and places:

  • reverseGeocode(latitude:longitude:) async throws -> [GeocodedPlace]
  • geocode(address:maxResults:) async throws -> [GeocodedPlace]
  • isAvailable (always true on Darwin; Geocoder.isPresent() on Android)

No matches return []. Failed lookups throw GeocodingError.

Platform implementation

API
Darwin 26+ MKReverseGeocodingRequest / MKGeocodingRequest
Darwin < 26 CLGeocoder
Android 33+ Geocoder listener API (onGeocode and onError both handled, so a failed lookup can't hang)
Android < 33 Blocking Geocoder API on Dispatchers.IO

Open question: field coverage on iOS 26+

MapKit's OS 26 types (MKAddress, MKAddressRepresentations) don't expose
subLocality, administrativeArea, or postalCode as separate fields, so
those are nil on that path. CLGeocoder and Android's Geocoder provide all
of them. The README has a per-platform table. If you'd rather keep CLGeocoder
as the only Darwin path until MapKit covers these fields, I'm happy to change it.

Testing

  • swift test: passes on macOS and on Robolectric (13 passed, 2 skipped).
  • skip android build (bridged / Skip Fuse): builds.
  • xcodebuild builds for iOS and watchOS.
  • Live lookup test (opt-in via SKIP_DEVICE_LIVE_GEOCODING=1) passes on macOS 27 (MapKit path).
  • Not yet run on a device: the CLGeocoder fallback (iOS < 26) and a real Android geocoder.

Note: tvOS doesn't build on main either (AccelerometerProvider imports CoreMotion), so that failure isn't from this change.

Adds GeocodingProvider with reverseGeocode(latitude:longitude:) and
geocode(address:maxResults:), returning [GeocodedPlace].

- Darwin: MKReverseGeocodingRequest/MKGeocodingRequest on OS 26+,
  falling back to CLGeocoder on earlier versions.
- Android: Geocoder's listener API on API 33+, and the blocking API
  on Dispatchers.IO below that. isAvailable reflects Geocoder.isPresent().
- Empty results return [] rather than throwing; lookup failures throw
  GeocodingError.

MapKit's OS 26 types do not expose subLocality, administrativeArea or
postalCode separately, so those fields are nil on that path.
Covers blank-field normalisation, joining address parts, blank queries,
and mapping an android.location.Address into GeocodedPlace. A live
lookup test runs only when SKIP_DEVICE_LIVE_GEOCODING is set, so CI
does not depend on the network or geocoder rate limits.
Adds a Geocoding section with usage examples, a GeocodedPlace property
table showing per-platform field coverage, and the INTERNET permission
requirement, plus entries in the permissions summary and API reference.
@cla-bot cla-bot Bot added the cla-signed label Oct 27, 2026
@gurmeherchawla

Copy link
Copy Markdown
Author

Kindly review @marcprux

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant