mapbox-ios-patterns

작성자: mapbox

iOS용 Mapbox Maps SDK의 공식 통합 패턴입니다. 설치, 마커 추가, 사용자 위치, 사용자 정의 데이터, 스타일, 카메라 제어 등을 다룹니다.

npx skills add https://github.com/mapbox/mapbox-agent-skills --skill mapbox-ios-patterns

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

  1. File → Add Package Dependencies
  2. Enter URL: https://github.com/mapbox/mapbox-maps-ios.git
  3. Version: "Up to Next Major" from 11.0.0
  4. 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.

Which API should I use?

APIUse it whenPlatformsNotes
Marker (Markers API)You need a default pin and don't have a custom image assetSwiftUI onlyNo image assets required. Experimental SPI — needs @_spi(Experimental) import MapboxMaps. Best < 100 markers.
PointAnnotationYou have a custom image and want layer-level placementSwiftUI + UIKitBacked 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 coordinateSwiftUI + UIKitSwiftUI 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. Marker and PointAnnotation each 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 a GeoJSONSource and render it with a SymbolLayer instead. 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:

  1. MBXAccessToken in Info.plist
  2. ✅ Token is valid (test at mapbox.com)
  3. ✅ MapboxMaps framework imported
  4. ✅ MapView added to view hierarchy
  5. ✅ 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 .standard style (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 Annotations
  • references/location-tracking.md — Camera Follow User + Get Current Location
  • references/custom-data.md — GeoJSON: Lines, Polygons, Points, Update/Remove
  • references/camera-styles.md — Camera Control + Map Styles
  • references/interactions.md — Featureset Interactions, Custom Layer Taps, Long Press, Gestures

Additional Resources

mapbox의 다른 스킬

mapbox-android-patterns
mapbox
Android용 Mapbox Maps SDK의 공식 통합 패턴입니다. 설치, 마커 추가, 사용자 위치, 사용자 정의 데이터, 스타일, 카메라 제어 등을 다룹니다.
official
mapbox-cartography
mapbox
지도 디자인 원칙, 색채 이론, 시각적 위계, 타이포그래피, 효과적이고 아름다운 지도를 제작하기 위한 지도학적 모범 사례에 대한 전문적인 안내…
official
mapbox-data-visualization-patterns
mapbox
지도 위에 데이터를 시각화하는 패턴으로, 코로플레스 맵, 히트 맵, 3D 시각화, 데이터 기반 스타일링, 애니메이션 데이터를 포함합니다. 레이어 유형 등을 다룹니다.
official
mapbox-geospatial-operations
mapbox
문제 유형, 정확도 요구 사항 및 성능 요구 사항에 따라 적합한 지리공간 도구를 선택하는 전문가 안내
official
mapbox-google-maps-migration
mapbox
Google Maps Platform에서 Mapbox GL JS로 전환하는 개발자를 위한 마이그레이션 가이드로, API 대응, 패턴 변환 및 주요 차이점을 다룹니다.
official
mapbox-location-grounding
mapbox
Mapbox MCP 도구를 구성하여 훈련 데이터 대신 실시간 데이터로부터 근거가 있고 인용된 위치 인식 응답을 생성합니다.
official
mapbox-maplibre-migration
mapbox
MapLibre GL JS에서 Mapbox GL JS로 마이그레이션하기 위한 가이드로, API 호환성, 토큰 설정, 스타일 구성 및 Mapbox 공식 기능의 이점을 다룹니다.
official
mapbox-mcp-devkit-patterns
mapbox
Mapbox MCP DevKit Server를 AI 코딩 어시스턴트에 통합하는 패턴입니다. 설정, 스타일 관리, 토큰 관리, 검증 워크플로우 등을 다룹니다.
official