Environment
- Xcode version: 26.5
- iOS version: 26.5
- Devices affected: all iOS devices
- Maps SDK Version: 11.25.1
Observed behavior and steps to reproduce
When using a custom LocationProvider/HeadingProvider (via mapView.location.override(locationProvider:headingProvider:)), the heading value supplied by the custom provider gets an additional rotation applied whenever the interface orientation isn't portrait. This comes from LocationManager.adjust(heading:toViewOrientation:), which combines every heading source with orientationProvider.onInterfaceOrientationChange and applies a fixed adjustment (landscapeLeft: -90, landscapeRight: +90, portraitUpsideDown: 180) regardless of where the heading came from.
Repro:
let customProvider = MyFixedHeadingProvider() // emits a constant heading, e.g. 95°
mapView.location.override(locationProvider: customProvider, headingProvider: customProvider)
Rotate the device/simulator to landscape — the puck bearing shifts by ~90° even though the custom provider's heading value never changed.
Our custom-provider integration code has not changed in months on either platform, and Android's behavior has remained correct throughout that window — a fixed heading renders identically regardless of device rotation there. Only iOS's behavior changed (confirmed working on Maps SDK 11.16.6, broken on 11.25.1) while the surrounding integration code was untouched, which points to the adjustment behavior changing within mapbox-maps-ios itself rather than in any consuming code.
Expected behavior
A custom HeadingProvider exists specifically to let an app supply a heading independent of the device's physical orientation — for example, a heading that follows the bearing of an active navigation route rather than which way the device is facing. LocationManager currently can't distinguish that from a CLHeading-style compass reading, so it applies the same orientation compensation intended for AppleLocationProvider to every heading source. The LocationDataModel.heading doc comment states "the heading values should not be adjusted to the user interface orientation... LocationManager adjusts the user interface orientation internally," which describes this behavior as intentional, but doesn't scope it away from custom, orientation-independent heading sources — for which this adjustment is simply incorrect. Android's LocationComponentPlugin doesn't apply an equivalent adjustment for custom providers, so parity with Android would also mean not adjusting custom-provided headings on iOS.
Notes / preliminary analysis
Confirmed working correctly on 11.16.6, confirmed broken on 11.25.1 — haven't bisected the exact version it was introduced in. We've worked around this on our side by pre-compensating the heading before it reaches the SDK, so the repro above is verified against actual behavior, not just code inspection.
Additional links and references
Adjustment logic: https://github.com/mapbox/mapbox-maps-ios/blob/main/Sources/MapboxMaps/Location/LocationManager.swift#L233
Doc comment describing (partial) intent: LocationDataModel.heading in the same file

Environment
Observed behavior and steps to reproduce
When using a custom
LocationProvider/HeadingProvider(viamapView.location.override(locationProvider:headingProvider:)), the heading value supplied by the custom provider gets an additional rotation applied whenever the interface orientation isn't portrait. This comes fromLocationManager.adjust(heading:toViewOrientation:), which combines every heading source withorientationProvider.onInterfaceOrientationChangeand applies a fixed adjustment (landscapeLeft: -90,landscapeRight: +90,portraitUpsideDown: 180) regardless of where the heading came from.Repro:
Rotate the device/simulator to landscape — the puck bearing shifts by ~90° even though the custom provider's heading value never changed.
Our custom-provider integration code has not changed in months on either platform, and Android's behavior has remained correct throughout that window — a fixed heading renders identically regardless of device rotation there. Only iOS's behavior changed (confirmed working on Maps SDK 11.16.6, broken on 11.25.1) while the surrounding integration code was untouched, which points to the adjustment behavior changing within
mapbox-maps-iositself rather than in any consuming code.Expected behavior
A custom
HeadingProviderexists specifically to let an app supply a heading independent of the device's physical orientation — for example, a heading that follows the bearing of an active navigation route rather than which way the device is facing.LocationManagercurrently can't distinguish that from aCLHeading-style compass reading, so it applies the same orientation compensation intended forAppleLocationProviderto every heading source. TheLocationDataModel.headingdoc comment states "the heading values should not be adjusted to the user interface orientation...LocationManageradjusts the user interface orientation internally," which describes this behavior as intentional, but doesn't scope it away from custom, orientation-independent heading sources — for which this adjustment is simply incorrect. Android'sLocationComponentPlugindoesn't apply an equivalent adjustment for custom providers, so parity with Android would also mean not adjusting custom-provided headings on iOS.Notes / preliminary analysis
Confirmed working correctly on 11.16.6, confirmed broken on 11.25.1 — haven't bisected the exact version it was introduced in. We've worked around this on our side by pre-compensating the heading before it reaches the SDK, so the repro above is verified against actual behavior, not just code inspection.
Additional links and references
Adjustment logic: https://github.com/mapbox/mapbox-maps-ios/blob/main/Sources/MapboxMaps/Location/LocationManager.swift#L233
Doc comment describing (partial) intent:
LocationDataModel.headingin the same file