Refine iOS Navigation: SwiftUI + drop-in NVC default - #75
Conversation
Default to SwiftUI + MapboxNavigationCore (CoreSDKExample), move UIKit/NavigationViewController to an opt-in reference, and require agents to list upstream Examples before answering so new samples stay discoverable. Co-authored-by: Cursor <cursoragent@cursor.com>
Restore ios-navigation-sdk.md to the PR #12 UIKit content so it merges cleanly, and route the default iOS path through the new SwiftUI reference. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Thanks for this, and nice work on the verification, I checked the actual upstream repo against most of the specific claims here (CoreSDKExample's Navigation.swift, the tripSession methods, Constants.swift's listOfExamples, the Road Cameras example) and it all holds up. Ran the full check suite on the actual branch in an isolated worktree too, that's clean. Two things I want addressed before this merges:
Small thing, not blocking: eval #16 checks for the literal method signature |
|
Re-reviewed after the latest push, both things I flagged last time are fixed. ios-navigation-swiftui.md is gone and everything's consolidated into one file, and the live-fetch requirement is now an inline catalog with fetch as opt-in only. I cross-checked all 22 rows in the Example patterns catalog against the real Constants.swift listOfExamples on mapbox-navigation-ios, all match exactly. Ran the full eval suite on the actual branch too: 98% (194/198). One small gap from that eval run worth a quick fix: eval #17 (Road Cameras) scored 83% because the response never mentioned that AdditionalExamples samples are typically UIKit-based even though Core/SwiftUI is the default elsewhere in the skill. Could you add a line to the catalog's intro along those lines, something like "note: most AdditionalExamples samples are UIKit, adapt the pattern to Core/SwiftUI unless the user wants UIKit directly"? Not blocking, just tightens up that one case. Also, we talked through whether to inline more of the 22 examples the way Android inlined route line/camera/voice, and decided against it. The current shape (two inlined defaults plus a catalog pointer for the long tail) is the right scope, pulling in all 22 would add maintenance surface without much real benefit given most of them are pretty niche. Good to merge from my side once the catalog intro line is in. |
|
Need to walk back my "good to merge" from before. I verified the code in this PR was accurate, but I didn't check whether defaulting to Core+SwiftUI custom UI over UIKit is actually the right call, and it isn't, at least not based on what Mapbox's own current official docs recommend. I pulled the mapbox-navigation-ios README and the docs.mapbox.com tutorial "Add turn-by-turn navigation to an iOS app" (the current, official getting-started guide). Both use SwiftUI for the app's own screens, sure, but for the actual navigation experience they wrap the UIKit I think this PR conflates two separate things: what UI framework the app is built in (SwiftUI vs UIKit) and whether the user wants the drop-in navigation experience or a fully custom one. Those are independent. The official answer for "I'm building a SwiftUI app, add navigation" is: keep SwiftUI for your own screens, wrap the drop-in
Would want to see the default flipped to: SwiftUI app shell + UIViewControllerRepresentable-wrapped NavigationViewController as the default path, with the Core+Combine fully-custom UI (CoreSDKExample) as the opt-in for people who explicitly want to build their own nav UI instead of using the drop-in one. |
Default to SwiftUI wrapping NavigationViewController, keep CoreSDKExample as opt-in custom UI, and note that AdditionalExamples catalog samples are typically UIKit-based. Co-authored-by: Cursor <cursoragent@cursor.com>
Inline multi-stop waypoints, route line styling, navigation camera, road cameras, and route alerts from the Examples catalog; leave niche AdditionalExamples as catalog-only. Co-authored-by: Cursor <cursoragent@cursor.com>
Retain MapboxNavigationProvider in Core snippets, add a greenfield setup checklist, and recommend progress.distanceRemaining for total remaining distance. Co-authored-by: Cursor <cursoragent@cursor.com>
CI failed on Unknown word (netrc) in the iOS Navigation setup checklist. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Re-reviewed after the latest push. The default fix is right and I verified it, not just read the description. New default is exactly the official pattern, SwiftUI app shell + NavigationViewController wrapped in UIViewControllerRepresentable, with CoreSDKExample's fully custom Core UI now clearly opt-in. Went through the new content carefully since there's a lot of it now (multi-stop, route line styling, navigation camera, road cameras, route alerts). Checked all of it against real SDK source, NavigationOptions.swift, RouteProgress.swift, NavigationMapView.swift, and the actual upstream examples. It all holds up. The Road Cameras section's Ran the full eval suite on the actual branch: 95.5% (189/198). One real gap worth fixing before merge: Eval #17 dropped to 67% (was around 83% before). Asked specifically about Road Cameras, the model said the example is "stack independent" and works the same for SwiftUI drop-in or custom Core UI, which actually contradicts the nuance we wanted. The catalog table's general note about AdditionalExamples being UIKit based isn't strong enough on its own, the model didn't connect it to this specific inline section. Can you add that caveat directly in the Road Cameras section itself, not just the catalog intro? Smaller thing: eval #1 dipped to 80%, missed the MAU vs pay-per-request pricing point entirely. Pre-existing eval, not iOS specific, probably just crowded out by how much more implementation detail is in the response now. Worth a glance but not blocking. One structural note, not blocking either: the file's at 455 lines now, up from 270 last round, well past the under-200-lines guideline in CONTRIBUTING.md for reference files. Not enforced by validate:skills and it covers a lot of genuinely distinct ground now (setup, three UI approaches, five specialized patterns, voice, antipattern). Might be worth splitting the specialized topics (multi-stop, route line, camera, road cameras, alerts) into a second reference file the way Android already separates android-navigation-sdk.md from android-performance-antipatterns.md, before it grows further. |
Treat AdditionalExamples as UIKit demo hosts, not UIKit-only APIs: wrap NavigationMapView in a SwiftUI representable for waypoints, route line, camera, and callouts; attach road cameras to MapboxMap via MapReader. Co-authored-by: Cursor <cursoragent@cursor.com>
CI format:check failed on table alignment in ios-navigation-sdk.md. Co-authored-by: Cursor <cursoragent@cursor.com>
Promote Sample host vs API stack to h2 so markdownlint MD001 passes. Co-authored-by: Cursor <cursoragent@cursor.com>
…onMapView. Move multi-stop, route line, camera, road cameras, and alerts into ios-navigation-specialized.md. Wire road cameras from NavigationMapView.mapboxMap plus Core navigatorHandle instead of MapReader. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Re-reviewed after the latest push. Both things from last round are handled well. The file split worked out nicely. ios-navigation-sdk.md is down to 310 lines, and the new ios-navigation-specialized.md (multi-stop, route line, camera, road cameras, alerts) is 165, under the guideline. Good separation, matches how Android splits basic patterns from antipatterns. The sample host vs API stack framing is a better fix than what I suggested, not just a caveat, it draws a real distinction between the demo app's UI framework and whether the specific API is UIKit-only. Checked it, NavigationMapView really is Ran the full eval suite on the actual branch: 99.1% (211/213). Both regressions from last round are gone, pricing point's back to 100%, eval #17 recovered to 93%, and the new eval #18 (the "do I have to switch to UIKit" scenario) scores 100%. One real issue I found while checking the Road Cameras rewrite, evals won't catch this since it's a compile time thing not a fact check. This won't compile: guard let mapboxMap = navigationMapView.mapView.mapboxMap else { return }
Good to merge once that one line's fixed. |
NavigationMapView.mapView.mapboxMap is non-optional; drop the invalid guard let. Co-authored-by: Cursor <cursoragent@cursor.com>
thank you! great call, ready. |
8595eff
into
add-navigation-patterns-skill
* Add mapbox-navigation-patterns skill Adds navigation and routing patterns skill covering the Directions API and Navigation SDKs for web, iOS, and Android, rebased onto main. Also adds **/build/ to .prettierignore to prevent Prettier from trying to parse Android build artifacts in the demos directory. Co-Authored-By: mattpodwysocki <mattpodwysocki@gmail.com> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix broken links in navigation and data-visualization skills - optimization-v2 URL 404s; replaced with optimization (v1) URL - simplestatistics.org domain-squatted; replaced with GitHub Pages URL Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Address review feedback: default to driving-traffic profile, document lon/lat order - Default all Directions/Optimization API examples to the driving-traffic profile (live traffic, congestion, incidents); driving is now called out only for the arrive_by case, since driving-traffic doesn't support it - Document that coordinates are always longitude,latitude order - Switch the basic map example to the Mapbox Standard style - Rename "Traffic-Aware Routing" to "Congestion-Based Route Coloring" now that traffic-awareness is the default, not an opt-in section - Reword the "Web routing" product-decision row and note the geojson vs polyline6 tradeoff for the geometries parameter Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Fix table formatting per prettier Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Split SKILL.md into references/ to satisfy the 500-line skill guideline SKILL.md was 1160 lines; moved implementation code (web directions API, iOS/Android nav SDK patterns, best practices, common use cases) into references/, leaving SKILL.md as a short overview + decision guide with links out. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Add evals/evals.json to satisfy skill validation requirements Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Address review feedback: use lifecycle-aware MapboxNavigationApp on Android MapboxNavigationProvider.create()/destroy() doesn't survive configuration changes and required manual lifecycle wiring. Switch both Android examples to MapboxNavigationApp.setup() + requireMapboxNavigation(), matching the official mapbox-navigation-android-examples pattern, and link to that repo as the canonical source for anything beyond the basics. * Fix eval.js default model: claude-sonnet-4-20250514 has been retired npm run eval was failing with a 404 not_found_error for anyone not overriding EVAL_MODEL/EVAL_JUDGE_MODEL, since the hardcoded default model ID is no longer served by the API. Default to claude-sonnet-5 instead. * Fix Optimization API and congestion-coloring eval gaps - State the Optimization v1 API's 12-coordinate hard limit explicitly, and that source/destination only accept 'first'/'any' and 'last'/'any' (not numeric indices). Fixed a latent bug in the example's own parameter handling (startIndex/endIndex compared against string literals that could never match their own default values). - Clarify the "advanced use cases" note as Optimization API v2 specifically (separate async job-submission API, Public Beta, up to 1,000 locations) rather than an unlabeled reference, per docs.mapbox.com/api/navigation/optimization. - Add overview=full to the congestion-coloring example; annotations must be paired with it or the geometry won't line up with the per-segment array. Verified against current Mapbox docs (Optimization v1, Optimization v2, Directions API). Eval score: 93% (53/57) -> 100% (57/57). * Add RouteLine guide * Add Maneuver Arrow rendering section * Add Navigation Camera * Update examples to use lateinit * Add VoiceGuidance * Add Performance & Correctness Antipatterns reference file * Add eval coverage for the new Android route line and antipattern content Two new cases: - #6: route line rendering (MapboxRouteLineApi/View, RoutesObserver-driven updates, teardown) — targets the new Route Line Rendering section. - #7: code-review style prompt targeting NAV-NRO-1/NAV-NRO-3 (manual route traversal instead of RouteProgress.distanceRemaining) and NAV-MEMORY-3 (unregistered inline observer) from the new antipatterns reference. Score: 98.8% (80/81) on first pass with the finalized prompts. * Add iOS RouteProgress anti-pattern, ported from the Android NAV-NRO guidance Same underlying principle as Android's NAV-NRO-1 (don't recompute what RouteProgress already exposes), adapted to iOS's Combine-based RouteProgress/RouteLegProgress/RouteStepProgress structs. Explicitly does not carry over Android's native-object-accessor-cost performance claim, since that hasn't been verified against iOS SDK internals — only the correctness/duplication point is asserted. Added eval #8 targeting this. Full suite: 100% (90/90). * Add more evals.json for navsdk * Update Route Maneuver Arrows example. Scenario: After using skill to build demo app, on first try maneuver arrow was under route line. * Update android-navigation-sdk.md with information that examples are explaining NavSDK integration and they are not handling all scenarios application need to consider. * [QUAL] Fix text formatting * [DEV] Update skills to increase eval grade * Refine iOS Navigation: SwiftUI + drop-in NVC default (#75) * Make iOS Navigation skill Core-first with live Examples validation. Default to SwiftUI + MapboxNavigationCore (CoreSDKExample), move UIKit/NavigationViewController to an opt-in reference, and require agents to list upstream Examples before answering so new samples stay discoverable. Co-authored-by: Cursor <cursoragent@cursor.com> * Split Core/SwiftUI iOS nav into ios-navigation-swiftui.md. Restore ios-navigation-sdk.md to the PR #12 UIKit content so it merges cleanly, and route the default iOS path through the new SwiftUI reference. Co-authored-by: Cursor <cursoragent@cursor.com> * Work in progress. * Align iOS Navigation default with official drop-in-in-SwiftUI path. Default to SwiftUI wrapping NavigationViewController, keep CoreSDKExample as opt-in custom UI, and note that AdditionalExamples catalog samples are typically UIKit-based. Co-authored-by: Cursor <cursoragent@cursor.com> * Add high-value inline iOS Navigation example patterns. Inline multi-stop waypoints, route line styling, navigation camera, road cameras, and route alerts from the Examples catalog; leave niche AdditionalExamples as catalog-only. Co-authored-by: Cursor <cursoragent@cursor.com> * Harden iOS Navigation skill defaults for agent correctness. Retain MapboxNavigationProvider in Core snippets, add a greenfield setup checklist, and recommend progress.distanceRemaining for total remaining distance. Co-authored-by: Cursor <cursoragent@cursor.com> * Allow netrc in the spellcheck dictionary. CI failed on Unknown word (netrc) in the iOS Navigation setup checklist. Co-authored-by: Cursor <cursoragent@cursor.com> * Clarify iOS NavigationMapView APIs as stack-independent. Treat AdditionalExamples as UIKit demo hosts, not UIKit-only APIs: wrap NavigationMapView in a SwiftUI representable for waypoints, route line, camera, and callouts; attach road cameras to MapboxMap via MapReader. Co-authored-by: Cursor <cursoragent@cursor.com> * Format the iOS Navigation reference for Prettier. CI format:check failed on table alignment in ios-navigation-sdk.md. Co-authored-by: Cursor <cursoragent@cursor.com> * Fix markdown heading increment in the iOS Navigation reference. Promote Sample host vs API stack to h2 so markdownlint MD001 passes. Co-authored-by: Cursor <cursoragent@cursor.com> * Split iOS specialized nav topics and align Road Cameras with NavigationMapView. Move multi-stop, route line, camera, road cameras, and alerts into ios-navigation-specialized.md. Wire road cameras from NavigationMapView.mapboxMap plus Core navigatorHandle instead of MapReader. Co-authored-by: Cursor <cursoragent@cursor.com> * Fix non-optional mapboxMap access in Road Cameras snippet. NavigationMapView.mapView.mapboxMap is non-optional; drop the invalid guard let. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: mattpodwysocki <mattpodwysocki@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Artur Bogusławski <artur.boguslawski@mapbox.com> Co-authored-by: Artem Stepuk <7859322+ArtemStepuk@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Summary
Stacked on #12 (
add-navigation-patterns-skill). Updates iOS Navigation only, aligned with current official Mapbox getting-started guidance and review feedback on this PR.NavigationViewControllerviaUIViewControllerRepresentableNavigationViewControllerdirectlyreferences/ios-navigation-sdk.mdAdditionalExamplesare UIKit demo hosts. AUIViewControllersample does not mean the API is UIKit-only.NavigationMapViewAPIs are stack-independent — wrapNavigationMapViewinUIViewRepresentableand configure the same entities (custom waypoint / final-waypoint image, waypoint styling, route line, camera, callouts)MapboxMapAPIs (road cameras) attach to any map — SwiftUIMapReader(proxy.map) ornavigationMapView.mapView.mapboxMapSKILL.md,AGENTS.md, README blurb, and evals (including Add spell check entries for new skills #17 road cameras + Add Pattern 6: Delivery/Logistics Map #18 NMV/waypoints) accordinglyAndroid/Web navigation content from #12 is unchanged. Maps and Search skills are untouched. Does not inline all AdditionalExamples implementations.
Test plan
npm run validate:skills(and format/spell/lint as usual)NavigationViewControllerRoadCamerasManager+RoadCamerasMapController+MapReader