Skip to content

URGENT fix(ios): honor maximumAge in getCurrentPosition instead of returning stale cached positions - #90

Open
binikingi wants to merge 3 commits into
ionic-team:mainfrom
binikingi:fix/ios-maximum-age
Open

URGENT fix(ios): honor maximumAge in getCurrentPosition instead of returning stale cached positions#90
binikingi wants to merge 3 commits into
ionic-team:mainfrom
binikingi:fix/ios-maximum-age

Conversation

@binikingi

@binikingi binikingi commented Jul 21, 2026

Copy link
Copy Markdown

Description

On iOS, getCurrentPosition ignores the maximumAge option entirely and can resolve with a stale cached position. This PR makes the iOS implementation honor maximumAge as documented (and as Android and Web already do): a position older than maximumAge no longer satisfies getCurrentPosition — the call stays pending while a fresh position is acquired (falling back to continuous updates when needed), still bounded by the existing timeout handling.

Details of the change:

  • maximumAge is now read from getCurrentPosition calls (stored alongside the existing shared timeout, same last-caller-wins semantics).
  • Positions delivered by the location service are checked against maximumAge before resolving pending single-location calls. Because CLLocation timestamps lag delivery by the acquisition time, positions younger than a 5s freshness threshold are always accepted, so the default maximumAge: 0 keeps resolving with freshly acquired fixes.
  • When a stale position is rejected and no watch is running, the plugin starts monitoring to force a fresh fix (re-arming the timeout timer, which the stale delivery had cancelled) and stops monitoring again once the request is satisfied. If a watch is already running, the next live update resolves the call.
  • Watch callbacks are unaffected: they continue to receive every update, including the ones rejected for single requests.

Context

There are two ways iOS currently hands back stale coordinates:

  1. CLLocationManager.requestLocation() frequently delivers the system's last known location — taken minutes earlier, before the device moved — and nothing checks its timestamp.
  2. Since IONGeolocationLib 2.x, requestSingleLocation returns the in-memory currentLocation verbatim whenever monitoring is active, with no freshness check at all.

Either way the position carries its original (good) accuracy value, so callers have no signal that the coordinates are outdated. In our production home-care app, caregivers clocking in at a patient's home get positions 1.5–3 miles away — reported as accuracy: ~16m — because the fix predates their drive over.

This is very likely the same root cause behind #68 and #69 ("wrong coordinates on iOS, fine on Android/Web"), both closed for lack of response. The answer to the question asked there ("are you receiving outdated location?") is yes: the coordinates are outdated, and only position.timestamp reveals it.

Type of changes

  • Fix (non-breaking change which fixes an issue)

Platforms affected

  • iOS

Tests

  • npm run verify:ios (xcodebuild) builds successfully.
  • SwiftLint: no new violations (the two nesting warnings on GeolocationConstants.swift pre-date this change).
  • The existing iOS test target is a template stub that references a class that no longer exists, so no unit tests were added here; happy to add coverage (e.g. via an injectable IONGLOCService fake) if you can point me at the preferred approach.
  • Manual verification in a production app: with this patch, a getCurrentPosition call issued right after arriving at a new location waits for a live fix instead of resolving with the pre-drive cached position.

Screenshots (if appropriate)

Checklist

  • Code follows code style of this project

@binikingi

Copy link
Copy Markdown
Author

Hi is anyone here?

@binikingi binikingi changed the title fix(ios): honor maximumAge in getCurrentPosition instead of returning stale cached positions URGENT fix(ios): honor maximumAge in getCurrentPosition instead of returning stale cached positions Aug 5, 2026
@OS-ruimoreiramendes OS-ruimoreiramendes self-assigned this Aug 13, 2026
@OS-ruimoreiramendes

Copy link
Copy Markdown
Contributor

Hi @binikingi, thanks for the thorough writeup and the very clear reproduction steps. I reproduced the stale behavior and confirmed your fix eliminates it.

Before merging, one placement concern: I think this fix belongs in ion-ios-geolocation rather than in the plugin.

  • The root cause lives in the lib: IONGLOCManagerWrapper.requestSingleLocation sends currentLocation as-is with no freshness check.
  • maximumAge isn't part of IONGLOCRequestOptionsModel today, adding it there brings the model in line with what callers need.
  • Android already works this way: maximumAge is enforced by the native lib, so fixing iOS at the same layer restores parity.

Would you be open to moving the change to the lib? The plugin change would then collapse to just passing the option through. For local testing you can point the plugin's SPM dependency at your fork so you can iterate against the same app.

Thanks again for the contribution!

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.

2 participants