Mapbox welcomes participation and contributions from everyone.
MapView rendering blank when attached to an already-active CarPlay scene.PointAnnotation.image or StyleManager.addImage.FeaturesetFeature.originalFeature property.MapboxMap.onStyleAttributionsChanged, use this event to observe when attributions have been changed due to style change, source metadata change, or if sources were removed or added.Marker with two animation triggers: appear and disappear. Each trigger accepts MarkerAnimationEffect including wiggle (pendulum rotation), scale, fadeIn, and fadeOut. Effects can be customized with parameters (e.g., scale(from: 0.5, to: 1.5), fade(from: 0.5, to: 1.0)) and combined for rich animations. See MarkersExample for usage.LineLayer.lineElevationGroundScale property to scale elevated lines with terrain exaggeration.LineLayer.lineZOffset and LineLayer.lineElevationReference.SymbolScaleBehavior API to automatically scale map symbols (icons and text) based on system accessibility text size settings. Set MapboxMap.symbolScaleBehavior property to configure: .system (automatic scaling), .system(mapping:) (custom mapping function), or .fixed(scaleFactor:) (fixed scale, default is 1.0). Valid scale factor range is [0.8, 2.0]. Automatic scaling is opt-in; symbols default to fixed 1.0x scale.ModelSource support with Model, ModelMaterialOverride, and ModelNodeOverride to enable interactive 3D models. Material overrides allow customization of color, emissive strength, opacity, and color mix intensity. Node overrides enable control of model part transformations such as rotating doors, landing gear, or propellers. Models can be updated via source-driven approach (modifying ModelSource.models directly) or feature-state driven approach (using expressions with feature state for dynamic control). For implementation examples, see Interactive3DModelFeatureStateExample (SwiftUI), Interactive3DModelSourceExample (UIKit), and Animated3DModelSourceExample (SwiftUI).queryRenderedRasterValues API for querying the rendered raster array value at a point on the map.FrameViewAnnotationsExample annotations disappearing before shadow leaves the screen.CameraOptions instead of crashing.ModelLayer.modelAllowDensityReduction property to disable density reduction in model layers.colorBuildings, colorCommercial, colorEducation, colorIndustrial, colorLand, colorMedical, show3dBuildings, show3dFacades, show3dLandmarks, and show3dTrees.shadowDrawBeforeLayer property to directional light to allow specifying the position in the layer stack for drawing shadows on the ground.userData payload for onSourceDataLoaded event during GeoJSON partial update.@_spi(Experimental) from Geofencing APIs.ModelLayer to stable.SymbolLayer.occlusionOpacityMode, SymbolLayer.iconColorBrightnessMax, SymbolLayer.iconColorBrightnessMin, SymbolLayer.iconColorContrast properties.FillExtrusionLayer.castShadows property.GeoJSONSource.minZoom property.RasterArraySource.volatile experimental property.line-emissive-strength property data-driven.MapboxMap.setFeatureStateExpression(), removeFeatureStateExpression(), and resetFeatureStateExpressions() APIs to efficiently update feature state for multiple features at once using expressions.MapboxMap.setLayerProperty(), setLayerProperties and updateLayer().ScaleBarViewOptions.units property supporting metric, imperial, and nautical units, replacing the boolean useMetricUnits property.OrnamentsManager when setting attribution color.fuelingStationModePointOfInterestLabels configuration option to Mapbox Standard and Standard Satellite styles. Control the visibility of fuel station and electric charging station POI labels with options: default (shows both), fuel (fuel stations only), electric (charging stations only), or none (hides both).MapInitOptions.mapStyle property. Use it to initialize map with a custom style.// Before
let options = MapInitOptions(styleURI: .standardSatellite)
let mapView = MapView(frame: view.bounds, mapInitOptions: options)
mapView.mapboxMap.setStyleImportConfigProperties(for: "basemap", configs: ["lightPreset": "dusk"])
// After:
let options = MapInitOptions(mapStyle: .standardSatellite(lightPreset: .dusk))
let mapView = MapView(frame: view.bounds, mapInitOptions: options)
StyleReloadPolicy to control style reload behavior. Use reloadPolicy: .always parameter in loadStyle() methods or MapStyle initializers to always reload the style even when the URI or JSON matches the currently loaded style. Defaults to .onlyIfChanged for optimal performance.LocationManager.locationDataModel and make it possible to use location provider from MapboxCommon. Deprecate the LocationManager.override* methods.
Now you can choose to use the location provider from MapboxCommon.@_spi(Experimental) import MapboxMaps
// UIKit
let initOptions = MapInitOptions(
locationDataModel: .createCore()
)
let mapView = MapView(mapInitOptions: initOptions) // specify at init time (recommended)
mapView.mapboxMap.locationDataModel = .createCore() // or, override it at runtime
// SwiftUI
struct MyView: View {
@State var locationDataModel = LocationDataModel.createCore()
var body: some View {
Map(viewport: $viewport) {
Puck2D(bearing: .heading)
}
.locationDataModel(locationDataModel)
}
}
scaleFactor param to MapOptions, MapSnapshotOptions for scaling icons and texts.LandmarkIcons featureset in Mapbox Standard Style. The LandmarkIcons featureset allows querying and configuring landmark building icons that appear on the map. Access landmark properties including landmarkId, name, type, and localized names through the StandardLandmarkIconsFeature class.MapStyle.standard() and MapStyle.standardSatellite() with new configuration parameters for color customization, landmark icons visibility, point-of-interest styling, road appearance, and administrative boundaries.LineLayer.lineCutoutFadeWidth to control route line cutout fade width.ExpressionArgumentBuilder. Now supports if/else conditions, for loops, optionals, and #available checks within expression builders. This allows more natural and readable expression construction, reducing boilerplate code when building complex map styling expressions.Marker component with onTapGesture modifierLineLayer.lineCutoutOpacity and LineLayer.lineCutoutWidth to make route lines visible through obstructing 3D buildings and other aboveground features.Marker convenience API in Swift UI. Use Marker to quickly add a MapViewAnnotation pin at the specified coordinates with custom text and color.Map {
Marker(coordinate: CLLocationCoordinate2D(...))
.text("My marker")
.color(.blue)
.stroke(.orange)
}
split expression, which returns an array of substrings from a string, split by a delimiter parameter.PointAnnotation image in Style DSLFillLayer.fillPatternCrossFade, FillExtrusionLayer.fillExtrusionPatternCrossFade, LineLayer.fillExtrusionPatternCrossFade properties.PointAnnotation.iconImageCrossFade has been deprecated and setting value to it will not have any impact. Use PointAnnotationManager.iconImageCrossFadeTransition instead.
The Interactions and Featuresets API is promoted from experimental. The new API allows you to add interaction handlers to layers, Standard Style featuresets (POI, Buildings and Place Labels), and the map itself in the consistent way. You can control the propagation of events, tappable area, and the order of event handling.
The experimental style MapStyle.standardExperimental is removed. Use MapStyle.standard instead.
Methods GestureManager.onMapTap, GestureManager.onMapLongPress, GestureManager.onLayerTap, GestureManager.onLayerLongPress and their SwiftUI counterparts are deprecated. Use TapInteraction and LongPressInteraction instead.
Add new VectorSource.promoteId2 and GeoJSONSource.promoteId2. Deprecate VectorSource.promoteId and GeoJSONSource.promoteId. The newer version support the expression variant of promoteId, which can be used to dynamically nominate IDs to the features.
// Before (SwiftUI)
Map()
.onMapTapGesture { context in
// Handle tap on map
}
.onLayerLongPressGesture("a-layer-id") { feature, context in
// Handle press on a layer
return true
}
// After (SwiftUI)
Map {
TapInteraction { feature in
// Handle tap on map
return true
}
LongPressInteraction(.layer("a-layer-id")) { feature, context in
// Handle press on a layer
return true
}
// Bonus: If you use Standard style, new API allows to handle tap on POI, Buildings and Place Labels
TapInteraction(.standardPoi) { poi, feature in
print("Tap on \(poi.name)")
return true
}
}
// Before (UIKit)
mapView.gestures.onMapTap.observe { context in
// Handle Tap on Map
}.store(in: &cancelables)
mapView.gestures.onLayerLongPress("a-layer-id") { feature, context in
// Handle Long press
return true
}
// After (UIKit)
mapView.mapboxMap.addInteraction(TapInteraction { context in
// Handle tap on map
return true
})
mapView.mapboxMap.addInteraction(LongPressInteraction(.layer("a-layer-id")) { feature, context in
// Handle long press on a layer
return true
})
// Bonus: If you use Standard style, new API allows to handle tap on POI, Buildings and Place Labels
mapView.mapboxMap.addInteraction(TapInteraction(.standardPoi) { poi, feature in
print("Tap on poi \(poi.name)")
return true
})
CircleLayer.circleElevationReference, FillLayer.fillConstructBridgeGuardRail, FillLayer.fillBridgeGuardRailColor, FillLayer.fillTunnelStructureColor.showLandmarkIcons property in MapStyle.standard.LineLayer/linezOffset.MapboxMap.screenCullingShape).graphicsPrograms, graphicsProgramsCreationTimeMillis and fboSwitchCount for CumulativeRenderingStatistics.top-image, bearing-image, and shadow-image properties on LocationIndicatorLayer are now paint properties instead of layout properties.let mapView = MapView()
mapView.mapboxMap.setMapStyleContent {
ColorTheme(base64: "base64EncodedImage") // or use an uiimage shortcut ColorTheme(uiimage: lutImage)
}
Note: Each style can have only one ColorTheme. Setting a new theme overwrites the previous one. Further details can be found in documentation for ColorTheme
ClipLayer.clipLayerTypes and ClipLayer.clipLayerScope to stable.DirectionalLight.shadowQuality.ViewAnnotationManager.viewAnnotationAvoidLayers for specifying layers that view annotations should avoid. The API currently only supports line layers.maxOverscaleFactorForParentTiles property in CustomRasterSource and CustomGeometrySource, allowing greater control over tile overscaling behavior when rendering custom raster tiles.SymbolElevationReference, FillExtrusionBaseAlignment, FillExtrusionHeightAlignment, ModelScaleMode, ModelType, ClipLayerTypes, BackgroundPitchAlignment types as Experimental. Initially they were exposed as stable by mistake. If you use them, please import MapboxMaps with Experimental SPI:@_spi(Experimental) import MapboxMaps
slot() method on annotation groups that takes Slot instead of String. Use the type with annotationGroups:swift
CircleAnnotationGroup {}
// old
.slot("middle")
// new
.slot(.middle)
ViewAnnotation.priority, deprecate ViewAnnotation.selected.
Use this property to define view annotation sort order.ViewAnnotation.minZoom and ViewAnnotation.maxZoom. Use these properties to configure zoom-level specific view annotations.StyleImage.Rain/centerThinning and Snow/centerThinning.MapView.resizingAnimation to .none.to-hsla expression support.⚠️⚠️⚠️ Potentially breaking changes ⚠️⚠️⚠️
Mark symbolElevationReference, symbolZOffset, lineTrimColor , lineTrimFadeRange, lineZOffset as Experimental in AnnotationManagers. This is potentially breaking change, however those properties are not marked as experimental only in AnnotationManagers by mistake.
In order to continue use them use the following import @_spi(Experimental) import MapboxMaps.
Add two separate Geofence examples in SwiftUI - GeofencingPlayground and GeofencingUserLocation
Add support for Base and Height alignment in FillExtrusionLayer.
Add support for pitchAlignment in BackgroundLayer.
Add support for zOffset in FillLayer, PolygonAnnotation[Manager] and PolygonAnnotationGroup.
Add a property emphasisCircleGlowRange to LocationIndicatorLayer to control the glow effect of the emphasis circle – from the solid start to the fully transparent end.
Fix a crash on calling LocationIndicatorLayer/location(coordinate:) function due to missing 0 altitude value.
Add a new Expression initializer init(_ operator: Operator, _ arguments: ExpressionArgumentConvertible...) to simplify the creation of expressions with multiple arguments.
That initializer doesn't require to wrap arguments in Argument cases. For example, Exp(.eq, Exp(.get, "extrude"), "true").
Expose a TileStore/clearAmbientCache() method to clear ambient cache.
Add new experimental radius parameter to TapInteraction, LongPressInteraction and interaction managers to control the radius of a tappable area.
Add a way to specify image expression options.
Bump core maps version to 11.9.0-beta.1 and common sdk to 24.9.0-beta.1
Add new experimental APIs to control precipitation rendering. Snow and Rain are available now with an @_spi(Experimental) import prefix.
Add a way to filter attribution menu items.
GeofencingPlayground and GeofencingUserLocationlineElevationReference, lineCrossSlope, iconSizeScaleRange, textSizeScaleRange as experimentalClipLayer as stable[SwiftUI] Fixed crash when ForEvery was used with duplicated IDs.
Introduce experimental Geofencing API. Implementation example: GeofencingExample.swift
Refactor of the experimental Interactions and Featuresets API:
InteractiveFeature is renamed to FeaturesetFeature.StandardPoiFeature, StandardBuildingsFeature, StandardPlaceLabelsFeature.FeaturesetDescriptor.Generate MapStyle.standard and MapStyle.standardSatellite from the style specification. Added the new StandardFont type to represent the font family in these configurations. If you used a string variable, update your code:
// Old:
Map().mapStyle(.standard(font: fontValue))
/// New:
Map().mapStyle(.standard(font: StandardFont(rawValue: fontValue)))
Map().mapStyle(.standard(font: .lato))
MapboxMap.styleGlyphURL. Use this property to apply custom fonts to the map at runtime, without modifying the base style.Source x missing for layer x) when using annotation managers.MapboxMaps-Swift.h from MapboxMaps framework, this will disable ObjC interop for MapboMaps.FillExtrusionLayer.fillExtrusionLineWidth that can switches fill extrusion rendering into wall rendering mode. Use this property to render the feature with the given width over the outlines of the geometry.Expose data-driven properties on annotation managers. Now it's possible to set data-driven properties globally on annotation manager and specify per-annotation overrides. Previously user had to specify those properties on each annotation and couldn't specify them globally
Added new experimental interactive features API. Interactive features allow you to add interactions to both layers, the map itself, or the features defined in the imported styles, such as Standard Style. The new API supersedes the Map Content Gesture API and makes it cross-platform.
Rename the MapContentGestuereContext to the InteractionContext
Introduce a new RenderedQueryGeometry type to replace multiple MapboxMaps.queryRenderedFeatures overloads.
[SwiftUI] Introduce new experimental FeatureState primitive.
Expose data-driven properties on annotation managers. Now it's possible to set data-dirven properties globally on annotation manager and specify per-annotation overrides. Previosuly user had to specify those properties on each annotation and couldn't specify them globally
CircleAnnotationGroup(circles, id: \.id) { circle in
CircleAnnotation(centerCoordinate: circle.coordinate)
.circleColor(circle.color)
.circleRadius(10)
.circleStrokeWidth(1)
.circleStrokeColor(.black)
}
The problem with the above approach is that most of the properties are just duplicated for each annotation, which can lead to large memory overhead in case of big datasets. In order to solve this issue and provide more versatile API the following approach is now possible, which is visually identical to previous snippet, but more performant.
CircleAnnotationGroup(circles, id: \.id) { circle in
CircleAnnotation(centerCoordinate: circle.coordinate)
.circleColor(circle.color)
}
.circleRadius(10)
.circleStrokeWidth(1)
.circleStrokeColor(.black)
Same applies for imperative API. In this case each even annotation will have random color, but others will use the global default specified in the annotation manager.
let circleAnnotationManager = mapView.annotations.makeCircleAnnotationManager()
var annotations = [CircleAnnotation]()
for i in 0...2000 {
var annotation = CircleAnnotation(centerCoordinate: .random)
if i % 2 == 0 { annotation.circleColor = StyleColor(.random) }
annotations.append(annotation)
}
circleAnnotationManager.circleColor = .blue
Improve memory reclamation behavior when using partial GeoJSON update API.
Update Turf to 3.0.0 version. That version introduce breaking change – there is no more RawRepresentable conformances for Array and Dictionary system types. If you were relying on the init(rawValue:) function or rawValue property, you can use the substitution instead:
init(rawValue:) -> init(turfRawValue:)rawValue -> turfRawValueRemove experimental model-front-cutoff property from ModelLayer
Bump core maps version to 11.7.0-beta.2 and common sdk to 24.7.0-beta.2
Expose experimental ClipLayer.clipLayerScope, SymbolLayer.symbolElevationReference and SymbolLayer.symbolZOffset.
Most of public value types was marked as Sendable now, to facilitate adoption of Swift 6 concurrency model for SDK clients.
autoMaxZoom property exposed for GeoJSONSource to fix rendering issues with FillExtrusionLayer in some cases
MapOptions.orientation, MapOptions.constrainMode and MapOptions.viewportMode.lineTrimColor and lineTrimFadeRange on LineLayer which allow to set custom color for trimmed line and fade effect for trim. Update navigation example to use those properties.⚠️⚠️⚠️ Known Issues ⚠️⚠️⚠️
ClipLayer property clipLayerTypes is not updated in runtime. The fix is expected to land in stable 11.6.0.⚠️⚠️⚠️ Known Issues ⚠️⚠️⚠️
ClipLayer property clipLayerTypes is not updated in runtime. The fix is expected to land in 11.6.0-rc.1.ClipLayer to remove 3D data (fill extrusions, landmarks, trees) and symbols.CustomRasterSource API updated, now CustomRasterSourceOptions accepts protocol CustomRasterSourceClient, enabling direct rendering into CustomRasterSource tiles. To achieve behavior similar to previous releases one may construct instance of CustomRasterSourceClient as shown below:CustomRasterSourceOptions(tileStatusChangedFunction: { tileID, status in }) // Before
CustomRasterSourceOptions(clientCallback: CustomRasterSourceClient.fromCustomRasterSourceTileStatusChangedCallback { tileID, status in }) // Now
ViewAnnotation.allowZElevate and MapViewAnnotation.allowZElevate properties. When set to true, the annotation will be positioned on the rooftops of buildings, including both fill extrusions and models.MapView.presentsWithTransaction and Map.presentsWithTransaction in favor of MapView.presentationTransactionMode and Map.presentationTransactionMode. The new default PresentationTransactionMode.automatic updates the presentsWithTransaction automatically when need to optimize performance. If you used the MapView.presentsWithTransaction with View Annotations, now you can safely remove this option:Map {
MapViewAnnotation(...)
}
.presentsWithTransaction(true) // Remove this
In case you need to preserve the old default behavior use presentationTransactionMode = .async:
mapView.presentationTransactionMode = .async // UIKit
Map().presentationTransactionMode(.async) // SwiftUI
maccatalyst platform and code signing issues was eliminated.line-pattern precisionCustomRasterSource rendering when camera shows anti-meridian or multiple world copies.LineJoin.none in conjunction with an image as a linePattern value to display repeated series of images along a line(e.g. dotted route line).Expression in favor of Exp to avoid name clash with Foundation.Expression.FollowPuckViewportState.clusterMinPoints property for GeoJSONSource and for ClusterOptionsAtmosphere, Lights, Projection, Terrain, Transition) are now revertible for all styles.Atmosphere, Lights, Projection, Terrain, Transition) are now revertible for all styles.CameraForExample showcasing camera(for:) usageqRasterParticleLayer which is suitable for displaying precipitation or wind on the mapViewAnnotationMapboxMap.loadStyle() and Snapshotter.loadStyle() behaviour is rolled back to pre 11.4.0-beta.1 state.⚠️⚠️⚠️ Known Issues ⚠️⚠️⚠️
RasterLayer’s rasterColor property with an expression will block the layer from rendering. This issue will be resolved in v11.4.0-rc.1.In this release, we introduce the new Declarative Styling API for UIKit and SwiftUI. This change is based on MapContent introduced for SwiftUI; therefore, it has been restructured. The changes are compatible; however, in some rare cases, you may need to adjust your code.
MapContent now supports custom implementations, similar to SwiftUI views. The MapContent protocol now requires the var body: some MapContent implementation.// Before
PointAnnotation()
.iconOffset([10, 20]) // x, y
.iconTextFitPadding([1, 2, 3, 4]) // top, right, bottom, left
Puck3D()
.modelScale([1, 2, 3]) // x, y, z
// After
PointAnnotation()
.iconOffset(x: 10, y: 20)
.iconTextFitPadding(UIEdgeInsets(top: 1, left: 4, bottom: 3, right: 2))
Puck3D()
.modelScale(x: 1, y: 2, z: 3)
StyleImportConfiguration was removed from public API, the MapStyle now contains the configuration directly.TransitionOptions is now a Swift struct rather than an Objective-C class.MapContent in SwiftUI.@_spi(Experimental) MapboxMaps
Map {
LineLayer(id: "traffic")
.lineColor(.red)
.lineWidth(2)
}
setMapStyleContent to use style primitives:@_spi(Experimental) MapboxMaps
mapView.mapboxMap.setMapStyleContent {
LineLayer(id: "traffic")
.lineColor(.red)
.lineWidth(2)
}
Allow to assign slot to 2D and 3D location indicators.
Allow observing start/stop event of CameraAnimator
You can observe start/stop event of CameraAnimator by using new CameraAnimationsManager APIs as shown below
// Observe start event of any CameraAnimator owned by AnimationOwner.cameraAnimationsManager
mapView.camera
.onCameraAnimatorStarted
.owned(by: .cameraAnimationsManager)
.observe { cameraAnimator in
// Handle camera animation started here.
}
.store(in: &cancelables)
// Observe finished events of any CameraAnimator
mapView.camera
.onCameraAnimatorFinished
.observe { animator in
// Handle camera animation stopped here.
}
.store(in: &cancelables)
You can also observe directly on an instance of CameraAnimator when using low-level camera APIs to create a custom animator
// Declare an animator that changes the map's bearing
let bearingAnimator = mapView.camera.makeAnimator(duration: 4, curve: .easeInOut) { (transition) in
transition.bearing.toValue = -45
}
bearingAnimator.onStarted.observe {
// Bearing animator has started.
}.store(in: &cancelables)
Allow adding slots at runtime.
Expose API to interact with style imports using Declarative Styling and regular imperative API.
onClusterTap and onClusterLongPress to AnnotationManagers(UIKit) and AnnotationGroups(SwiftUI) which support clusteringdragBeginHandler, dragChangeHandler, dragEndHandler to all Annotation types.captureSnapshot on MapProxy which allows to capture SwiftUI Map snapshot using MapReaderopaque and frameRate on SwiftUI MapallowHistTesting modifier on MapViewAnnotation..ignoresSafeArea(.all)includeOverlays parameter to MapView.snapshot()ViewAnnotation and MapViewAnnotation.CameraAnimationsManager.fly(to:duration:curve:completion), make TimingCurve public with few more options.MapboxMap.centerAltitudeMode and ensure correct centerAltitudeMode on gesture ending.MapboxMap: setNorthOrientation(_:), setConstrainMode(_:) and setViewportMode(_:).
Use them to configure respective map options after creating a map view.MapboxMap.reduceMemoryUse() which can be used in situations when it is important to keep the memory footprint minimal.MapboxMap.isAnimationInProgress and MapboxMap.isGestureInProgress to query current status of both built-in and custom camera animations and gestures.CustomRasterSource and non-experimental CustomGeometrySource as regular Source's providing a better way to work with them and also allow for using them in Style DSL.tileCacheBudget property on GeoJsonSource, RasterSource, RasterDemSource, RasterArraySource, VectorSource, CustomGeometrySource, and CustomRasterSource.MapboxMaps/setTileCacheBudget(size:) will now use the TileCacheBudgetSize property, the older method with TileCacheBudget has been deprecated and will be removed in a future major release.SymbolLayer.iconColorSaturation API.RasterLayer.rasterElevation API.MapboxMap.collectPerformanceStatistics allowing to collect map rendering performance statistics, both for UIKit and SwiftUI.Expose StyleImport for declarative styling as MapStyleContent.
Expose removeStyleImport, moveStyleImport, updateStyleImport, addStyleImport methods on StyleManager
Allow assigning layerPosition to 2D and 3D location indicators in imperative API.
Make Puck2D and Puck3D to be positioned according to relative layer position in declarative API instead of always top-most position.
Add codesign for XCFrameworks.
MapboxMap.loadStyle() and Snapshotter.loadStyle() now correctly call the completion closure.