mapbox / mapbox/mapbox-maps-ios
Standard style renders one frame with broken 3D-light state on first hard zoom-out (once per process, device only)
Nobody has claimed this yet.
- Dominant language
- Swift
- Stars
- 601
- Forks
- 196
- PR merge metrics
- No merged PRs in 30d
Description
## Environment
- Xcode version: 17F113 (Xcode 17.x)
- Maps SDK Version: 11.26.0 (SwiftUI `Map`)
- iOS version: 26.5.2
- Devices affected: iPhone 15 Pro (reproduced); **not reproducible in the iOS Simulator**
## Observed behavior
Exactly **once per app process**, the first fast zoom-out from street level (~z17) toward region level renders **a single frame with broken 3D-light state**:
- With `lightPreset: .night` the frame renders near-white (a "white flash" over a dark map).
- With `lightPreset: .day` the same glitch renders **dark** instead.
The inversion with light preset suggests the frame is drawn with the Standard style's lighting missing/defaulted. The glitch never repeats within the same process — every later zoom-out is clean. On a 120Hz device the frame lasts ~8ms; 60fps screen recordings often miss it entirely (we caught it with a 120fps recording and per-frame luma analysis: the glitch frame's average luma was 235/255 against a ~50 baseline for surrounding frames).
Verified by frame capture: UIKit/SwiftUI overlays and view annotations composite normally over the glitch frame — only the map surface is affected. No style events fire around it (`onStyleLoaded` fires exactly once, at startup).
Tested one variable at a time, each in a fresh process (required, since the glitch is once-per-process):
| Variable | Result |
|---|---|
| theme `.faded` vs `.default` | flashes either way |
| lightPreset `.night` vs `.day` | flashes either way, color inverts |
| `presentationTransactionMode` `.sync` / `.async` / `.automatic` | flashes in all |
| bare `Map` with no annotations/content | still flashes |
| pinch gesture vs programmatic `withViewportAnimation` | both trigger |
| iOS Simulator | never reproduces |
## Expected behavior
No frame should render without the configured light preset applied.
## Steps to reproduce
Run the view below on a **physical device** (fresh launch), and watch the first zoom-out:
```swift
import MapboxMaps
import SwiftUI
struct ReproView: View {
@State private var viewport: Viewport = .camera(
center: CLLocationCoordinate2D(latitude: 31.2304, longitude: 121.4737),
zoom: 10
)
var body: some View {
Map(viewport: $viewport) {}
.mapStyle(.standard(theme: .faded, lightPreset: .night, showPlaceLabels: false))
.ignoresSafeArea()
.task {
let center = CLLocationCoordinate2D(latitude: 31.2304, longitude: 121.4737)
try? await Task.sleep(for: .seconds(5))
while !Task.isCancelled {
withViewportAnimation(.easeIn(duration: 1.0)) {
viewport = .camera(center: center, zoom: 17)
}
try? await Task.sleep(for: .seconds(1.6))
withViewportAnimation(.easeOut(duration: 0.9)) {
viewport = .camera(center: center, zoom: 4)
}
try? await Task.sleep(for: .seconds(1.5))
}
}
}
}
```
The first zoom-out of the process flashes; subsequent cycles never do. Because a 60fps recording can miss the 8ms frame, verify with a 120fps capture or by eye on-device.
## Workaround
Running one hidden zoom-in/zoom-out cycle (z17 → z4) while the map is occluded consumes the glitch off-screen; after that the process never flashes again.
Happy to provide the frame captures / luma traces from our analysis if useful.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the SwiftUI ReproView on a physical iPhone 15 Pro, using a fresh app process and the provided first zoom-out sequence. Verify the behavior with a 120Hz capture, then compare the first cycle with later cycles and the simulator. Done means no frame renders without the configured light preset during the initial zoom-out.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- ios, swift
- Domain
- computer-graphics, mobile
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 43/100