The iOS 17 MapKit API customizes a Map through modifiers: mapStyle for the cartography,
interactionModes for gestures, and mapControls or mapScope for the control views.
Map Styles
mapStyle picks between standard (the default), imagery (satellite), and hybrid (imagery
plus roads and names). Each style configures elevation; standard and hybrid also filter
points of interest and toggle traffic.
Map { /* content */ }
.mapStyle(.imagery(elevation: .realistic))
.mapStyle(
.standard(
elevation: .flat,
pointsOfInterest: .excluding([.store]),
showsTraffic: false
)
)
.mapStyle(
.hybrid(
elevation: .flat,
pointsOfInterest: .including([.airport]),
showsTraffic: true
)
)
Limiting Gestures
All map gestures are on by default. Pass a set to interactionModes to allow only some of
pan, pitch, rotate, and zoom.
Map(interactionModes: [.pan, .pitch]) { /* content */ }
Map Controls
Importing MapKit with SwiftUI brings control views: MapScaleView, MapCompass,
MapPitchToggle, MapUserLocationButton, and MapZoomStepper. Inside mapControls, SwiftUI
places them per platform.
Map { /* content */ }
.mapControls {
MapScaleView()
MapCompass()
}
Placing Controls Yourself
The controls are plain views, so they can live anywhere in the hierarchy. To bind one to a
specific map, create an identifier with @Namespace, pass it as the map's scope, pass the same
value to each control, and close the loop with mapScope.
struct MapScopeExample: View {
@Namespace private var favoritesMap
var body: some View {
VStack {
Map(scope: favoritesMap) { /* favorite pins */ }
HStack {
MapScaleView(scope: favoritesMap)
MapCompass(scope: favoritesMap)
.mapControlVisibility(.hidden)
}
}
.mapScope(favoritesMap)
}
}
mapControlVisibility overrides the automatic visibility with always visible or hidden.