mcpField
M
mapbox-ios-patterns

mapbox-ios-patterns

github.com/mapbox开发831.5k 次安装4 周前更新
代码仓库

关于 mapbox-ios-patterns

该技能整理 Mapbox Maps SDK v11 在 iOS 上的集成模式,面向使用 Swift、SwiftUI 或 UIKit 开发地图应用的人员。内容包括地图初始化、标注、位置显示、自定义数据和交互,并提供性能与排错建议。

主要功能

  1. 01SwiftUI 与 UIKit 地图初始化
  2. 02添加标记和注释
  3. 03显示用户位置与相机跟随
  4. 04加载 GeoJSON 自定义数据
  5. 05地图样式与交互处理
  6. 06注释性能和生命周期建议

适用场景

  1. 01在 iOS 应用中集成 Mapbox 地图
  2. 02为地点添加自定义标记
  3. 03在地图上呈现用户位置
  4. 04处理地图要素点击与手势

安装

复制下面的命令,在终端中运行。

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

安装后在 Claude Code 中输入/mapbox-ios-patterns确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

AGENTS.md
evals/
evals.json
references/
annotations.md
camera-styles.md
custom-data.md
interactions.md
location-tracking.md

详细介绍

Mapbox iOS 集成模式

使用 Swift、SwiftUI 和 UIKit 在 iOS 上集成 Mapbox Maps SDK v11 的官方模式。

在以下情况下使用此技能:

  • 安装和配置 Mapbox Maps SDK for iOS
  • 向地图添加标记和注释
  • 显示用户位置并跟踪相机移动
  • 向地图添加自定义数据(GeoJSON)
  • 使用地图样式、相机或用户交互
  • 处理要素交互和点击

官方资源:


安装与设置

要求
  • iOS 14+
  • Xcode 15+
  • Swift 5.9+
  • 免费的 Mapbox 账户
步骤 1:配置访问令牌

将公开令牌添加到 Info.plist:

<key>MBXAccessToken</key>
<string>pk.your_mapbox_token_here</string>

**获取令牌:**登录 mapbox.com

步骤 2:添加 Swift Package 依赖项
  1. File → Add Package Dependencies
  2. 输入 URL:https://github.com/mapbox/mapbox-maps-ios.git
  3. **版本:**选择从 11.0.0 开始的 “Up to Next Major”
  4. 确认出现四个依赖项:MapboxCommon、MapboxCoreMaps、MapboxMaps、Turf

**替代方案:**CocoaPods 或直接下载(安装指南)


初始化地图

SwiftUI 模式

基本地图:

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

带装饰元素:

Map(viewport: $viewport)
    .mapStyle(.standard)
    .ornamentOptions(OrnamentOptions(
        scaleBar: .init(visibility: .visible),
        compass: .init(visibility: .adaptive),
        logo: .init(position: .bottomLeading)
    ))
UIKit 模式
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)
    }
}

添加标记

SDK 提供了三种在地图上放置点的方式。选择最适合需求的简单方案。

**Agent 说明:**SwiftUI Mapbox 草图至少需要包含一个注释(Marker、PointAnnotation 或 MapViewAnnotation),否则是不完整的。不要发布不带图钉的空 Map { }。

应该使用哪个 API?
API适用场景平台说明
Marker(Markers API)需要默认图钉,且没有自定义图像资源仅 SwiftUI无需图像资源。实验性 SPI——需要 @_spi(Experimental) import MapboxMaps。最适合少于 100 个标记的情况。
PointAnnotation有自定义图像,并希望在图层级别放置SwiftUI + UIKit基于符号图层,因此可良好扩展至数百个标记。接受任何可由 UIKit 渲染的 UIImage。
视图注释(ViewAnnotation / MapViewAnnotation)希望渲染完整的原生视图(卡片、徽章、动画内容),并将其锚定到坐标SwiftUI + UIKitSwiftUI 使用 MapViewAnnotation;UIKit 使用带有 ViewAnnotation 的 mapView.viewAnnotations。每个注释都是真实视图,大规模使用时比 PointAnnotation 消耗更多资源。

对于数百或数千个要素,请使用样式图层(GeoJSONSource 上的 SymbolLayer),而不是注释。

Markers API(适用于简单场景,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")
        }
    }
}

集合中的多个标记:

Map {
    ForEvery(locations, id: \.id) { location in
        Marker(coordinate: location.coordinate)
            .color(.red)
            .text(location.name)
    }
}

缩放说明。 Marker 和 PointAnnotation 会为每个标记分别创建一个视图或符号条目——处理约 100 个标记时没有问题。对于更大的数据集(数百或数千个要素;开放式 GeoJSON 数据源中很常见),请将数据加载到 GeoJSONSource 中,再使用 SymbolLayer 渲染。这样可以扩展到数千个要素,并支持聚类。

PointAnnotation(自定义图像)

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]

多个标记:

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

显示用户位置

步骤 1:在 Info.plist 中添加位置权限:

<key>NSLocationWhenInUseUsageDescription</key>
<string>Show your location on the map</string>

步骤 2:请求权限并显示位置:

import CoreLocation

// Request permissions
let locationManager = CLLocationManager()
locationManager.requestWhenInUseAuthorization()

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

性能最佳实践

重用注释管理器
// ❌ 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
}
批量更新注释
// ✅ Update all at once
pointAnnotationManager.annotations = newAnnotations

// ❌ Don't update one by one
for annotation in newAnnotations {
    pointAnnotationManager.annotations.append(annotation)
}
内存管理
// 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() }
}
使用标准样式
// ✅ Standard style is optimized and recommended
.mapStyle(.standard)

// Use other styles only when needed for specific use cases
.mapStyle(.standardSatellite) // Satellite imagery

故障排除

地图未显示

检查:

  1. ✅ Info.plist 中的 MBXAccessToken
  2. ✅ 令牌有效(在 mapbox.com 上测试)
  3. ✅ 已导入 MapboxMaps 框架
  4. ✅ MapView 已添加到视图层级中
  5. ✅ 已设置正确的框架/约束
样式未加载
mapView.mapboxMap.onStyleLoaded.observe { [weak self] _ in
    print("Style loaded successfully")
    // Add layers and sources here
}.store(in: &cancelables)
性能问题
  • 使用 .standard 样式(推荐且经过优化)
  • 将可见注释限制在视口范围内
  • 重用注释管理器
  • 避免频繁重新加载样式
  • 批量更新注释

参考文件

任务需要更深入的模式时,请加载以下参考资料:

  • references/annotations.md — 圆形、折线和多边形注释
  • references/location-tracking.md — 摄像机跟随用户 + 获取当前位置
  • references/custom-data.md — GeoJSON:线、多边形、点、更新/移除
  • references/camera-styles.md — 摄像机控制 + 地图样式
  • references/interactions.md — 要素集交互、自定义图层点击、长按、手势

其他资源

评论

支持 Markdown