mapbox-ios-patterns
mapbox/mapbox-agent-skills
Official Mapbox Maps SDK v11 integration patterns for iOS with Swift and SwiftUI.
What is mapbox-ios-patterns?
Provides official patterns for integrating Mapbox Maps SDK on iOS, covering installation, map initialization in SwiftUI and UIKit, adding markers and annotations, user location tracking, custom data layers, and performance best practices. Use this when building map features into iOS apps with Mapbox.
- Install and configure Mapbox Maps SDK v11 for iOS with Swift Package Manager or CocoaPods
- Initialize maps in SwiftUI and UIKit with viewport and camera control
- Add markers and annotations using Markers API, PointAnnotation, or ViewAnnotation
- Display user location with permission handling and bearing-aware puck
- Load and render custom GeoJSON data on maps
- Apply map styles and configure ornaments (compass, scale bar, logo)
How to install mapbox-ios-patterns
npx skills add https://github.com/mapbox/mapbox-agent-skills --skill mapbox-ios-patterns- iOS 14 or later
- Xcode 15 or later
- Swift 5.9 or later
- Free Mapbox account with access token from mapbox.com
How to use mapbox-ios-patterns
- 1.Sign up for a free Mapbox account and generate a public access token
- 2.Add your token to Info.plist under the MBXAccessToken key
- 3.Add Mapbox Maps SDK as a Swift Package dependency from https://github.com/mapbox/mapbox-maps-ios.git (version 11.0.0 or later)
- 4.Initialize a Map in SwiftUI with a viewport or in UIKit with MapInitOptions and mapboxMap.loadStyle()
- 5.Add markers using Marker (SwiftUI), PointAnnotation, or ViewAnnotation based on your use case
- 6.Request location permissions in Info.plist and enable user location with mapView.location.options.puckType
- 7.For large datasets (100+ features), load GeoJSON into a GeoJSONSource and render with a SymbolLayer instead of individual annotations
Use cases
- Building a location-based app that shows user position and nearby points of interest
- Adding custom markers from a database to a map in a travel or delivery app
- Displaying hundreds of features from GeoJSON without performance degradation using style layers
- Creating an interactive map with tap-to-select feature interactions
- Showing real-time location tracking with camera following user movement
- iOS developers building location-aware features
- SwiftUI and UIKit developers integrating Mapbox
- Mobile engineers working with geospatial data and mapping
- Developers needing official Mapbox SDK patterns and best practices
mapbox-ios-patterns FAQ
Use Marker for simple default pins in SwiftUI without custom images. Use PointAnnotation for custom images and layer-level control across SwiftUI and UIKit. Use ViewAnnotation/MapViewAnnotation when you need full native views (cards, badges) anchored to coordinates. For 100+ features, use GeoJSONSource with SymbolLayer instead.
Don't create individual annotations for hundreds or thousands of features. Instead, load your GeoJSON into a GeoJSONSource and render it with a SymbolLayer, which scales to thousands of features and enables clustering.
iOS 14+, Xcode 15+, and Swift 5.9+.
Add NSLocationWhenInUseUsageDescription to Info.plist, request permissions with CLLocationManager.requestWhenInUseAuthorization(), then enable the location puck with mapView.location.options.puckType = .puck2D().
No. Create the annotation manager once and reuse it by updating its annotations property, which is more efficient than creating new managers repeatedly.
Full instructions (SKILL.md)
Source of truth, from mapbox/mapbox-agent-skills.
name: mapbox-ios-patterns description: Official integration patterns for Mapbox Maps SDK on iOS. Covers installation, adding markers, user location, custom data, styles, camera control, and featureset interactions. Based on official Mapbox documentation.
Mapbox iOS Integration Patterns
Official patterns for integrating Mapbox Maps SDK v11 on iOS with Swift, SwiftUI, and UIKit.
Use this skill when:
- Installing and configuring Mapbox Maps SDK for iOS
- Adding markers and annotations to maps
- Showing user location and tracking with camera
- Adding custom data (GeoJSON) to maps
- Working with map styles, camera, or user interaction
- Handling feature interactions and taps
Official Resources:
Installation & Setup
Requirements
- iOS 14+
- Xcode 15+
- Swift 5.9+
- Free Mapbox account
Step 1: Configure Access Token
Add your public token to Info.plist:
<key>MBXAccessToken</key>
<string>pk.your_mapbox_token_here</string>
Get your token: Sign in at mapbox.com
Step 2: Add Swift Package Dependency
- File → Add Package Dependencies
- Enter URL:
https://github.com/mapbox/mapbox-maps-ios.git - Version: "Up to Next Major" from
11.0.0 - Verify four dependencies appear: MapboxCommon, MapboxCoreMaps, MapboxMaps, Turf
Alternative: CocoaPods or direct download (install guide)
Map Initialization
SwiftUI Pattern
Basic map:
import SwiftUI
import MapboxMaps
struct ContentView: View {
@State private var viewport: Viewport = .camera(
center: CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194),
zoom: 12
)
var body: some View {
Map(viewport: $viewport)
.mapStyle(.standard)
}
}
With ornaments:
Map(viewport: $viewport)
.mapStyle(.standard)
.ornamentOptions(OrnamentOptions(
scaleBar: .init(visibility: .visible),
compass: .init(visibility: .adaptive),
logo: .init(position: .bottomLeading)
))
UIKit Pattern
import UIKit
import MapboxMaps
class MapViewController: UIViewController {
private var mapView: MapView!
override func viewDidLoad() {
super.viewDidLoad()
let options = MapInitOptions(
cameraOptions: CameraOptions(
center: CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194),
zoom: 12
)
)
mapView = MapView(frame: view.bounds, mapInitOptions: options)
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(mapView)
mapView.mapboxMap.loadStyle(.standard)
}
}
Add Markers
The SDK offers three ways to place a point on the map. Pick the simplest one that fits.
Agent note: A SwiftUI Mapbox sketch is incomplete without at least one annotation (Marker, PointAnnotation, or MapViewAnnotation). Do not ship a bare Map { } with no pin.
Which API should I use?
| API | Use it when | Platforms | Notes |
|---|---|---|---|
Marker (Markers API) | You need a default pin and don't have a custom image asset | SwiftUI only | No image assets required. Experimental SPI — needs @_spi(Experimental) import MapboxMaps. Best < 100 markers. |
PointAnnotation | You have a custom image and want layer-level placement | SwiftUI + UIKit | Backed by a symbol layer, so it scales well to hundreds of markers. Accepts any UIImage that UIKit can render. |
View annotations (ViewAnnotation / MapViewAnnotation) | You want to render a full native view (card, badge, animated content) anchored to a coordinate | SwiftUI + UIKit | SwiftUI uses MapViewAnnotation; UIKit uses mapView.viewAnnotations with a ViewAnnotation. Each annotation is a real view — costs more than PointAnnotation at scale. |
For hundreds or thousands of features, use a style layer (SymbolLayer on a GeoJSONSource) instead of annotations.
Markers API (recommended for simple cases, SwiftUI)
import SwiftUI
@_spi(Experimental) import MapboxMaps
struct ContentView: View {
var body: some View {
Map {
Marker(coordinate: CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194))
.color(.red)
.text("San Francisco")
}
}
}
Multiple markers from a collection:
Map {
ForEvery(locations, id: \.id) { location in
Marker(coordinate: location.coordinate)
.color(.red)
.text(location.name)
}
}
Scaling note.
MarkerandPointAnnotationeach create their own view or symbol entry per pin — fine up to about 100 markers. For larger datasets (hundreds or thousands of features — common with open-ended GeoJSON feeds), load the data into aGeoJSONSourceand render it with aSymbolLayerinstead. That scales to thousands of features and enables clustering.
PointAnnotation (custom image)
SwiftUI:
Map(viewport: $viewport) {
PointAnnotation(coordinate: CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194))
.image(.init(image: UIImage(named: "marker")!, name: "marker"))
}
UIKit:
// Create annotation manager (once, reuse for updates)
var pointAnnotationManager = mapView.annotations.makePointAnnotationManager()
// Create marker
var annotation = PointAnnotation(coordinate: CLLocationCoordinate2D(latitude: 37.7749, longitude: -122.4194))
annotation.image = .init(image: UIImage(named: "marker")!, name: "marker")
annotation.iconAnchor = .bottom
// Add to map
pointAnnotationManager.annotations = [annotation]
Multiple markers:
let annotations = locations.map { coordinate in
var annotation = PointAnnotation(coordinate: coordinate)
annotation.image = .init(image: UIImage(named: "marker")!, name: "marker")
return annotation
}
pointAnnotationManager.annotations = annotations
Show User Location
Step 1: Add location permission to Info.plist:
<key>NSLocationWhenInUseUsageDescription</key>
<string>Show your location on the map</string>
Step 2: Request permissions and show location:
import CoreLocation
// Request permissions
let locationManager = CLLocationManager()
locationManager.requestWhenInUseAuthorization()
// Show user location puck
mapView.location.options.puckType = .puck2D()
mapView.location.options.puckBearingEnabled = true
Performance Best Practices
Reuse Annotation Managers
// ❌ Don't create new managers repeatedly
func updateMarkers() {
let manager = mapView.annotations.makePointAnnotationManager()
manager.annotations = markers
}
// ✅ Create once, reuse
let pointAnnotationManager: PointAnnotationManager
init() {
pointAnnotationManager = mapView.annotations.makePointAnnotationManager()
}
func updateMarkers() {
pointAnnotationManager.annotations = markers
}
Batch Annotation Updates
// ✅ Update all at once
pointAnnotationManager.annotations = newAnnotations
// ❌ Don't update one by one
for annotation in newAnnotations {
pointAnnotationManager.annotations.append(annotation)
}
Memory Management
// Use weak self in closures
mapView.gestures.onMapTap.observe { [weak self] context in
self?.handleTap(context.coordinate)
}.store(in: &cancelables)
// Clean up on deinit
deinit {
cancelables.forEach { $0.cancel() }
}
Use Standard Style
// ✅ Standard style is optimized and recommended
.mapStyle(.standard)
// Use other styles only when needed for specific use cases
.mapStyle(.standardSatellite) // Satellite imagery
Troubleshooting
Map Not Displaying
Check:
- ✅
MBXAccessTokenin Info.plist - ✅ Token is valid (test at mapbox.com)
- ✅ MapboxMaps framework imported
- ✅ MapView added to view hierarchy
- ✅ Correct frame/constraints set
Style Not Loading
mapView.mapboxMap.onStyleLoaded.observe { [weak self] _ in
print("Style loaded successfully")
// Add layers and sources here
}.store(in: &cancelables)
Performance Issues
- Use
.standardstyle (recommended and optimized) - Limit visible annotations to viewport
- Reuse annotation managers
- Avoid frequent style reloads
- Batch annotation updates
Reference Files
Load these references when the task requires deeper patterns:
references/annotations.md— Circle, Polyline, Polygon Annotationsreferences/location-tracking.md— Camera Follow User + Get Current Locationreferences/custom-data.md— GeoJSON: Lines, Polygons, Points, Update/Removereferences/camera-styles.md— Camera Control + Map Stylesreferences/interactions.md— Featureset Interactions, Custom Layer Taps, Long Press, Gestures
Additional Resources
Related skills
More from mapbox/mapbox-agent-skills and the wider catalog.

mapbox-maplibre-migration
Guide for migrating from MapLibre GL JS to Mapbox GL JS, covering API compatibility, token setup, style configuration, and the benefits of Mapbox's official support and ecosystem

mapbox-mcp-devkit-patterns
Integration patterns for Mapbox MCP DevKit Server in AI coding assistants.

mapbox-mcp-runtime-patterns
Integration patterns for Mapbox MCP Server in AI applications and agent frameworks. Covers runtime integration with pydantic-ai, mastra, LangChain, and custom agents. Use when building AI-powered applications that need geospatial capabilities.

mapbox-search-integration
Complete workflow for implementing Mapbox search in applications with discovery questions and best practices.

mapbox-search-patterns
Expert guidance on choosing the right Mapbox search tool and parameters for geocoding, POI search, and location discovery

mapbox-store-locator-patterns
Build store locators and location-based search apps with Mapbox GL JS patterns.