All skills
mapbox avatar

/mapbox-ios-patterns

@f5ae7de official
by mapboxmapbox/mapbox-agent-skills80 stars
17

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.

Use this Skill: https://skilld.dev/gh/mapbox/mapbox-agent-skills/mapbox-ios-patterns

This session only. Nothing lands on disk.

AGENTS.md

≈1.6k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Mapbox iOS Quick Reference

Fast reference for Mapbox Maps SDK v11 on iOS with Swift, SwiftUI, and UIKit.

Setup

Installation (SPM)

// File → Add Package Dependencies
https://github.com/mapbox/mapbox-maps-ios.git
// Version: 11.0.0+

Access Token

<!-- Info.plist -->
<key>MBXAccessToken</key>
<string>pk.your_token_here</string>

SwiftUI

Basic Map

import SwiftUI
import MapboxMaps

struct MapView: 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 Annotation

Map(viewport: $viewport) {
    PointAnnotation(coordinate: CLLocationCoordinate2D(
        latitude: 37.7749,
        longitude: -122.4194
    ))
    // Register and use the image in one call — raster UIImage only.
    .image(.init(image: UIImage(named: "marker")!, name: "marker"))
}
.mapStyle(.standard)

UIKit

Basic Map

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)
    }
}

Common Patterns

1. Add Markers

Three options — pick the simplest:

  • Marker (SwiftUI, experimental SPI) — default pin, no image assets.
  • PointAnnotation (SwiftUI + UIKit) — custom image, scales to hundreds via the underlying symbol layer.
  • View annotations (SwiftUI + UIKit) — arbitrary native view at a coordinate.
// Markers API — SwiftUI, simplest
import SwiftUI
@_spi(Experimental) import MapboxMaps

Map {
    Marker(coordinate: coord).color(.red).text("Coffee")
}

// PointAnnotation — UIKit, custom image
var manager = mapView.annotations.makePointAnnotationManager()

var annotation = PointAnnotation(coordinate: coordinate)
annotation.image = .init(image: UIImage(named: "marker")!, name: "marker")

manager.annotations = [annotation]

2. User Location with Camera Follow

import Combine

var cancelables = Set<AnyCancellable>()

// Request permission (add to Info.plist)
let locationManager = CLLocationManager()
locationManager.requestWhenInUseAuthorization()

// Show user location
mapView.location.options.puckType = .puck2D()
mapView.location.options.puckBearingEnabled = true

// Follow user location
mapView.location.onLocationChange.observe { [weak self] locations in
    guard let self = self, let location = locations.last else { return }

    self.mapView.camera.ease(to: CameraOptions(
        center: location.coordinate,
        zoom: 15,
        bearing: location.course >= 0 ? location.course : nil
    ), duration: 1.0)
}.store(in: &cancelables)

3. Add Custom Data (GeoJSON)

var source = GeoJSONSource(id: "route-source")
source.data = .geometry(.lineString(LineString(coordinates)))
try? mapView.mapboxMap.addSource(source)

var layer = LineLayer(id: "route-layer", source: "route-source")
layer.lineColor = .constant(StyleColor(.blue))
layer.lineWidth = .constant(4)
try? mapView.mapboxMap.addLayer(layer)

4. Camera Control

// Fly animation
mapView.camera.fly(to: CameraOptions(
    center: CLLocationCoordinate2D(latitude: 40.7128, longitude: -74.0060),
    zoom: 14
), duration: 2.0)

// Ease animation
mapView.camera.ease(to: CameraOptions(
    center: coordinate,
    zoom: 15
), duration: 1.0)

5. Featureset Interactions

// Tap on POI features
let token = mapView.mapboxMap.addInteraction(
    TapInteraction(.standardPoi) { poi, context in
        print("Tapped POI: \(poi.name ?? "Unknown")")
        return true
    }
)

// Tap on buildings
let buildingToken = mapView.mapboxMap.addInteraction(
    TapInteraction(.standardBuildings) { building, context in
        // Highlight the building using feature state
        self.mapView.mapboxMap.setFeatureState(
            building,
            state: ["select": true]
        )
        return true
    }
)

6. Map Tap Handling

mapView.gestures.onMapTap.observe { [weak self] context in
    let coordinate = context.coordinate
    print("Tapped at: \(coordinate)")
}.store(in: &cancelables)

7. Styles

// SwiftUI
.mapStyle(.standard)    // Recommended
.mapStyle(.streets)
.mapStyle(.dark)
.mapStyle(.standardSatellite)

// UIKit
mapView.mapboxMap.loadStyle(.standard)
mapView.mapboxMap.loadStyle(.dark)

Performance Tips

Reuse Managers

// ✅ Create once
let annotationManager = mapView.annotations.makePointAnnotationManager()

// ✅ Update many times
func updateMarkers() {
    annotationManager.annotations = newMarkers
}

Batch Updates

// ✅ Update all at once
manager.annotations = allAnnotations

// ❌ Don't update one by one
allAnnotations.forEach { manager.annotations.append($0) }

Memory Management

// Use weak self
mapView.gestures.onMapTap.observe { [weak self] context in
    self?.handleTap(context.coordinate)
}.store(in: &cancelables)

Use Standard Style

// ✅ Recommended
.mapStyle(.standard)

// Use others only when needed
.mapStyle(.standardSatellite)

Quick Checklist

✅ MBXAccessToken in Info.plist ✅ MapboxMaps imported ✅ Location permissions if needed ✅ Use .standard style (recommended) ✅ Weak self in closures ✅ Cancelables stored and cancelled ✅ Annotation managers reused

Resources

Source: SKILL.md on GitHub

1 warning17d5 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    The skill provides official integration patterns for the Mapbox Maps SDK on iOS, including installation, markers, location tracking, and custom data. It follows standard iOS development practices and utilizes official Mapbox resources. No security issues or malicious behaviors were detected.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • Runlayer7mo

    2/2 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at f5ae7de. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 9 hours ago.

Activeupdated 2 months ago
  • mapbox
  • ios
  • swift
  • swiftui
  • uikit
  • maps
  • annotations
  • geojson
  • location-tracking
  • camera-control

README badge

README badge for mapbox/mapbox-agent-skills/mapbox-ios-patterns

Installs and configures Mapbox Maps SDK v11 on iOS with Swift and SwiftUI, covering markers, user location, custom data layers, camera control, and feature interactions. Targets both SwiftUI and UIKit workflows and includes performance guidance for annotation management and style optimization.

Generated from the current SKILL.md.

Does this skill work with both SwiftUI and UIKit?
Yes. The skill covers both frameworks. Some APIs like `Marker` are SwiftUI-only, while `PointAnnotation` and `ViewAnnotation` work in both SwiftUI and UIKit.
What iOS version is required?
iOS 14 or later, with Xcode 15+ and Swift 5.9+. Mapbox Maps SDK v11 is the target version.
How do I handle hundreds or thousands of markers?
Use a `GeoJSONSource` with a `SymbolLayer` instead of individual annotations. The Markers and PointAnnotation APIs scale to about 100 markers; for larger datasets, load GeoJSON directly into a style layer, which scales to thousands of features and supports clustering.
Do I need a paid Mapbox account?
No. A free Mapbox account is sufficient to get an access token and use the Maps SDK.
How do I show the user's location on the map?
Add the location permission string to Info.plist, request `requestWhenInUseAuthorization()` from CLLocationManager, then enable the location puck with `mapView.location.options.puckType = .puck2D()`.

Generated from the current SKILL.md. These answers refresh after source changes.