Skip to content

MapKit Basics (SwiftUI)

A SwiftUI guide for coding agents. Also covers map view ios 17, mapkit markers annotations, mapcamera position, user location on map, map interaction modes, mapcontentbuilder.

The iOS 17 MapKit API replaces the old wrapped Map view with a full SwiftUI integration. Map takes a MapContentBuilder closure, a result builder like ViewBuilder but for types conforming to MapContent. The old Map is deprecated but still useful on earlier targets.

Markers and Annotations

Marker places a predefined pin. Annotation places any SwiftUI view at a coordinate. Other MapContent types include MapCircle, MapPolygon, MapPolyline, and UserAnnotation.

import MapKit
import SwiftUI

Map {
  Annotation("Seattle", coordinate: .seattle) {
    Image(systemName: "mappin")
      .foregroundStyle(.black)
      .padding()
      .background(.red)
      .clipShape(Circle())
  }

  Marker(coordinate: .newYork) {
    Label("New York", systemImage: "mappin")
  }

  Marker("San Francisco", monogram: Text("SF"), coordinate: .sanFrancisco)
}

Initial Camera Position

Map(initialPosition:) takes a MapCameraPosition. Build one from userLocation (with a fallback), or from the camera, region, rect, or item static functions. The default is automatic, which fits the map content.

let initialPosition: MapCameraPosition = .userLocation(
  fallback: .camera(
    MapCamera(centerCoordinate: .newYork, distance: 0)
  )
)

Map(initialPosition: initialPosition) {
  // markers
}

Binding the Camera

For continuous control, pass a binding. SwiftUI writes to it when the user drags the map, and moves the camera when your code sets the property.

@State private var position: MapCameraPosition = .userLocation(
  fallback: .camera(MapCamera(centerCoordinate: .newYork, distance: 0))
)

Map(position: $position) { /* content */ }

Restricting Interactions

The interactionModes parameter limits what the user can do. MapInteractionModes covers pan, pitch, rotate, and zoom; all are enabled by default.

Map(position: $position, interactionModes: .pitch) { /* content */ }

Use this guidance in your coding agent

Install the Better Design MCP once. Your agent then loads this page with one call.

get-swiftui-guide({ topic: "swiftui-mastering-mapkit-basics" })
claude mcp add --scope user better-design --transport http https://better-design.com/api/mcp --header "Authorization: Bearer <YOUR_API_KEY>"
Browse related design systems