Release Notes
Mappedin SDK for iOS release notes are posted here and this page will be kept up-to-date as updates are released.
6.3.0 - May 20, 2026
- Upgraded to Mappedin JS v6.19.0
Features
-
Added
visibleproperty toBlueDotOptions,AccuracyRing, andHeadingto control the visibility of Blue Dot components independently -
Added
AutoZoomThresholdsenum (.disabled,.enabled,.enabledWith(options:)) toDynamicFocusOptionsandDynamicFocusStatefor configuringDynamicFocusauto-zoom behavior
let options = DynamicFocusOptions(
autoZoomThresholds: .enabledWith(options: .init(debug: true))
)
- Added
.floorStack(FloorStack)case to theFocusTargetenum, with conveniencefocusOnandgetFocusOnTransformoverloads onCamerafor focusing on aFloorStack
mapView.camera.focusOn(.floorStack(floorStack))
-
Added
Events.cameraScreenOffsetsChangeevent to listen for camera screen offset changes -
Added
.pixels(String)case toWidthfor pixel-based width values (e.g."20px") -
Added
Navigation.trackCoordinatemethod for path tethering and travelled-path tracking, withTetheredOptions,TravelledOptions,TrackCoordinateOptions,TrackCoordinateResult,TrackingMode,CoordinateOutsideThresholdMode, andOutsideThresholdPathStylemodels
let handle = mapView.navigation.trackCoordinate(
origin: startCoordinate,
destinations: [destinationSpace],
options: TrackCoordinateOptions(
mode: .tethered,
tethered: TetheredOptions(
outsideThresholdMode: .smoothTransition,
outsideThresholdDistance: 5.0
)
)
) { result in /* ... */ }
mapView.blueDot.on(.dotPositionUpdate) { payload in
handle?.update(coordinate: payload.coordinate)
}
-
Added
BlueDotEvents.dotPositionUpdateevent that emits smoothedCoordinateupdates suitable for feeding intoNavigation.trackCoordinate -
Added
includeNonPublicproperty toGetDirectionsOptionsto allow routing through non-public spaces and connections -
Added
interactiveproperty toAddImageOptionsandinteractive/cursorproperties toImageStateandImageUpdateState.Image3DViewis now exposed inClickPayloadandHoverPayloadimagesandtarget
Deprecated
BlueDot.update()has been deprecated in favor ofBlueDot.forcePosition()orBlueDot.reportPosition()
// Before (deprecated)
mapView.blueDot.update(
position: BlueDotPositionUpdate(
latitude: .value(lat),
longitude: .value(lng),
floorId: .id(floorId)
),
options: BlueDotUpdateOptions(animate: true)
) { _ in }
// After
mapView.blueDot.reportPosition(
options: ManualPositionOptions(
latitude: lat,
longitude: lng,
floorLevel: floorLevel,
confidence: 1.0
)
) { _ in }
6.2.0 - April 2, 2026
-
Upgraded to Mappedin JS v6.17.1
-
Added -
BlueDot.forcePositionmethod to override all positioning sensors with a fixed position for a specified duration
let target = BlueDot.ForcePositionTarget(
latitude: 43.5186,
longitude: -80.5394,
heading: 90.0,
floorLevel: 1
)
mapView.blueDot.forcePosition(position: target, durationMs: 30000) { result in
// Position forced
}
- Added -
BlueDot.reportPositionmethod to feed a confidence-weighted position into the positioning fusion engine
let options = ManualPositionOptions(
latitude: 43.5186,
longitude: -80.5394,
accuracy: 5.0,
confidence: 0.8
)
mapView.blueDot.reportPosition(options: options) { result in
// Position reported
}
-
Added - Blue Dot sensor management methods:
enableSensor,disableSensor,checkSensorPermission,requestSensorPermission, andisSensorEnabledfor controlling individual positioning sensor sources -
Added -
BlueDotEvents.anchorSetandBlueDotEvents.anchorExpiredevents withPositionAnchorpayload for monitoring anchor lifecycle
mapView.blueDot.on(BlueDotEvents.anchorSet) { payload in
guard let anchor = payload?.anchor else { return }
print("Anchor set: \(anchor.sensorId) at \(anchor.latitude), \(anchor.longitude)")
}
-
Added -
floorGapMultiplierandfloorGapFallbackproperties toMultiFloorViewOptionsfor finer control over floor spacing in multi-floor view -
Added -
animatedproperty toAddMarkerOptionsto control whetherMarkers animate when added -
Added -
MaterialSide.autocase for automatic material side selection based on opacity -
Added -
EventsManagerAPI accessible viamapView.mapData.eventsManagerfor loading and querying CMS events. Includesload(),getEvents(),getById(), andgetByLocationId()methods
mapView.mapData.eventsManager.load { result in
if case .success = result {
mapView.mapData.eventsManager.getEvents { eventsResult in
if case .success(let events) = eventsResult {
for event in events {
print("\(event.name): \(event.startDate) - \(event.endDate)")
}
}
}
}
}
- Added -
positionproperty toShapeStateandShapeUpdateState, enabling reading and updating the position ofShapes
// Get the position of a shape
mapView.getState(shape: shape) { result in
if case .success(let state) = result {
print("Shape position: \(state?.position.latitude), \(state?.position.longitude)")
}
}
// Move a shape to a new position
let newPosition = Coordinate(latitude: 43.46, longitude: -80.52)
mapView.updateState(shape: shape, state: ShapeUpdateState(position: newPosition))
-
Added -
Models.all()method to load all CMS-defined 3DModels for a venue -
Added -
MultiFloorViewEffectStatemodel and related APIs for configuring visual effects on floors visible through open-to-belowSpaces in multi-floor view. Access the current state viaGlobalState.multiFloorViewand update it at runtime viaGlobalStateUpdate.multiFloorView
// Configure visual effects at init time
let options = Show3DMapOptions(
multiFloorView: MultiFloorViewOptions(
spacesOpenToBelowEnabled: true,
spacesOpenToBelowVisualEffectEnabled: true,
spacesOpenToBelowVisualEffectDarkenAmount: 0.3,
spacesOpenToBelowVisualEffectDesaturateAmount: 0.7
)
)
// Update visual effects at runtime
mapView.updateGlobalState(update: GlobalStateUpdate(
multiFloorView: GlobalStateUpdate.MultiFloorViewEffectStateUpdate(
spacesOpenToBelowVisualEffectDarkenAmount: 0.5
)
))
-
Added -
Events.globalStateChangeevent emitted whenupdateGlobalState()is called -
Fixed - an issue where facades could cover the map when calling
setMap
6.2.0-beta.1 - February 13, 2026
-
Upgraded to Mappedin JS v6.14.0
-
Added -
Query.atmethod to find all geometry objects (Spaces,MapObjects,Areas,Floors) at a given coordinate, with typed results returned asQueryAtResult
mapView.mapData.query.at(coordinate: coordinate) { result in
switch result {
case .success(let results):
results?.forEach { queryResult in
switch queryResult {
case .space(let space):
mapView.updateState(space: space, state: GeometryUpdateState(color: "#FF6B35"))
case .mapObject(let mapObject):
print("MapObject at point: \(mapObject.name)")
case .area(let area):
print("Area at point: \(area.name)")
case .floor(let floor):
print("Floor at point: \(floor.name)")
default:
break
}
}
case .failure(let error):
print("Query.at failed: \(error)")
}
}
-
Added -
FloorState.Images.collisionsEnabledproperty to control whether floor images participate in collision detection -
Added -
ModelUpdateState.clippingPlaneZOffsetproperty to control model clipping plane. Use.infinityto disable clipping
// Disable clipping for a model
let noClipState = ModelUpdateState(clippingPlaneZOffset: .infinity)
// Set explicit clipping plane offset
let clipState = ModelUpdateState(clippingPlaneZOffset: 5.0)
- Added -
DynamicFocusmethods for full API parity:preloadFloors()- Preloads initial floors for improved rendering performancesetIndoor()andsetOutdoor()- Forces indoor or outdoor view state regardless of zoom levelsetDefaultFloorForStack(floorStack:floor:)andresetDefaultFloorForStack(floorStack:)- Manages default floors forFloorStacksgetDefaultFloorForStack(floorStack:)andgetCurrentFloorForStack(floorStack:)- Gets default and current floorssetCurrentFloorForStack(floorStack:floor:)- Sets the current visible floor for aFloorStackexclude(floorStack:)/exclude(floorStacks:)andinclude(floorStack:)/include(floorStacks:)- Excludes or includesFloorStacks from Dynamic Focus visibility changesdestroy()- Destroys theDynamicFocusinstance and cleans up event listeners
// Force indoor view
dynamicFocus.setIndoor()
// Set current floor for a floor stack
dynamicFocus.setCurrentFloorForStack(floorStack: building.floorStack, floor: floor2) { _ in }
// Exclude a building from dynamic focus visibility changes
dynamicFocus.exclude(floorStack: parkingGarage.floorStack)
// Clean up when done
dynamicFocus.destroy()
- Added -
MapData.isEnterpriseModeproperty to determine whether the loaded map uses CMS/Enterprise or Maker data. Runtime warnings are now logged when requesting data types that do not match the active data source
mapView.mapData.isEnterpriseMode { result in
switch result {
case .success(let isEnterprise):
if isEnterprise {
mapView.mapData.getByType(.enterpriseLocation) { (locResult: Result<[EnterpriseLocation], Error>) in
// Handle enterprise locations
}
} else {
mapView.mapData.getByType(.locationProfile) { (locResult: Result<[LocationProfile], Error>) in
// Handle maker locations
}
}
case .failure(let error):
print("Error: \(error)")
}
}
6.2.0-beta.0 - February 2, 2026
-
Upgraded to Mappedin JS v6.13.0
-
Added -
BlueDotsupport viaMapView.blueDotextension with enable/disable/update/follow/getters and typed event subscriptions. Includes CoreLocation integration for native location and heading updates. New models includeBlueDotState,BlueDotOptions,BlueDotUpdateOptions,FollowMode, andFollowCameraOptions -
Added -
MapView.dynamicFocusextension providingenable,disable,getState,updateState, andfocusmethods for Dynamic Focus functionality. Includes new modelsDynamicFocusOptions,DynamicFocusState,DynamicFocusMode, andDynamicFocusAnimationOptions -
Added - Experimental
MapView.__EXPERIMENTAL__auto()method for automatic label and marker setup -
Added -
hydrateMapDataFromURL(url:options:)method for hydrating map data directly from a URL -
Added - Cache URL handling with
mappedin-cache://scheme and FileManager helper to build cache URLs -
Added - Support for loading maps from MVF filename for improved offline capabilities
-
Added -
LocationProfile.searchTagsproperty for accessing location search tags -
Added -
allFloorsoption toQuery.nearest()to search across all floors instead of just the current floor -
Added -
images3Dgetter toPointOfInterest,Space,Area, andMapObjectclasses with newImage3DViewmodel -
Improved - Map loading performance by optimizing how map data is passed to the WebView
6.2.0-alpha.3 - January 16, 2026
-
Upgraded to Mappedin JS v6.11.0
-
Added -
MapData.onmethod for subscribing to map data events. This enables listening for events such as language changes on the map data object. UseMapData.changeLanguageto change the current language and subscribe to changes usingMapDataEvents.languageChange
// Change the map language to Spanish
mapView.mapData.changeLanguage("es")
// Listen for language change events
mapView.mapData.on(MapDataEvents.languageChange) { payload in
if let language = payload {
print("Language changed to \(language.name) (\(language.code))")
}
}
-
Added -
FloorState.text3dproperty to access 3D text state for a floor -
Added -
LocationProfile.extraproperty to access additional profile data -
Added -
enterpriseLocationproperty toSpaceandMapObject, providing direct access to enterprise location data when available -
Added -
LocationProfile.logoImageproperty as a replacement for the deprecatedlogoproperty -
Added - Strongly typed
MapData.hydrateMapDataoptions parameter for better type safety when hydrating cached map data -
Added - Support for caching map data in binary format for improved offline performance
-
Added - Experimental support for Spaces that are open to below in multi-floor view. When enabled, floors will render with cutouts for Spaces like atriums that span multiple levels, creating a more realistic visualization. Enable this feature using
MultiFloorViewOptions.spacesOpenToBelowEnabled -
Added - New
MultiFloorViewOptionsproperties for customizing floor footprints in multi-floor view:footprintColor- Sets the color of the floor footprintfootprintOpacity- Controls the opacity of the floor footprintfootprintOutline- Configures the outline appearance of the floor footprint
-
Changed -
MultiFloorViewOptions.floorGapnow supports both a numeric value or anautosetting for automatic gap calculation between floors -
Fixed - Bridge serialization issue where
FloorStack.geoJSONand other complex GeoJSON properties were not being passed correctly over the native bridge. This resolves issues when accessing GeoJSON data from floor stacks and related objects -
Deprecated -
LocationProfile.logohas been deprecated in favor ofLocationProfile.logoImage
6.2.0-alpha.2 - January 8, 2026
- Upgraded to Mappedin JS v6.10.0
- Added - getDirections must also accept an array of NavigationTarget
- Added - Coordinate.geoJSON
- Fixed - mapView.updateState is not working on walls or doors
- Fixed - getDirectionsMultiDestination's to method should use NavigationTarget not Any
- Removed - Duplicated unused standalone classes of Point, LineString and MultiPolygon that are defined in Geometry
⚠️ Breaking Changes
- Changed - Clean up remaining generic types
- Changed - Strongly type .geoJSON properties
- Changed - Shapes.add should be strongly typed
// ❌ Before
// Get the GeoJSON from the area
guard let areaGeoJSON = area.geoJSON else { return }
// Create a FeatureCollection containing the Feature of the Area
var shapeFeatureCollection: [String: Any] = [
"type": "FeatureCollection",
"features": []
]
var feature: [String: Any] = [
"type": areaGeoJSON["type"] as? String ?? "Feature"
]
if let properties = areaGeoJSON["properties"] as? [String: Any] {
feature["properties"] = properties
}
if let geometry = areaGeoJSON["geometry"] as? [String: Any] {
feature["geometry"] = geometry
}
shapeFeatureCollection["features"] = [feature]
// Draw the shape
mapView.shapes.add(
geometry: shapeFeatureCollection,
style: PaintStyle(color: color, altitude: altitude, height: height, opacity: opacity)
) { _ in }
// ✅ After
// Get the GeoJSON Feature from the area
guard let feature = area.geoJSON else { return }
// Create a FeatureCollection containing the single Feature
let featureCollection = FeatureCollection(features: [feature])
// Draw the shape using the typed API
mapView.shapes.add(
geometry: featureCollection,
style: PaintStyle(color: color, altitude: altitude, height: height, opacity: opacity)
) { _ in }
6.2.0-alpha.1 - December 30, 2025
- Upgraded to Mappedin JS v6.9.1.
- Added -
Show3DMapOptions.preloadFloorsoption to preload floors. - Added -
MultiFloorViewOptions.floorGapoption to set the gap between floors. - Fixed -
Show3DMapOptions.initialFloorshould accept only a string.
⚠️ Breaking Changes
- Changed - Strongly type MapView.on parameters and return values
// ❌ Before
self.mapView.on("click") { [weak self] payload in
guard let self = self,
let clickPayload = payload as? ClickPayload,
}
// ❌ Before
self.mapView.on(Events.click) { [weak self] payload in
guard let self = self,
let clickPayload = payload as? ClickPayload,
}
// ✅ After
self.mapView.on(Events.click) { [weak self] clickPayload in
guard let self = self
}
6.1.0-alpha.1 - December 19, 2025
- Added - LabelAppearance.iconScale property to control the scale of the icon.
⚠️ Breaking Changes
- Fixed - Removed duplicate inline implementation of Interpolation and Width.
// ❌ Before
let opts = AddPathOptions(width: .fixed(1.0))
// ✅ After
let opts = AddPathOptions(width: .value(1.0))
- Fixed -
MapView.getStateandMapView.updateStateshould use data classes and not plain objects.
// ❌ Before
self.mapView.updateState(target: space, state: ["interactive": interactive]) { _ in }
// ✅ After
self.mapView.updateState(space: space, state: GeometryUpdateState(interactive: interactive))
6.0.0-alpha.0 - December 12, 2025
- Initial release of Mappedin SDK for iOS v6.