Skip to main content
Version: 6.0

Migration Guide

Mappedin SDK for iOS version 6.0 is a major release that includes a number of changes to the SDK. It uses a GeoJSON-based rendering engine, rebuilt from the ground up. It works in unison with MapLibre which enables outdoor base maps as well as data visualization features. By using GeoJSON as the core data format, v6 can integrate with existing external data sources. This guide explains the steps needed to migrate from version 5.

Initialization Changes

The options for getting a map have changed. getVenue() has been replaced by getMapData().

v5 Initialization

  // See Trial API key Terms and Conditions
// https://developer.mappedin.com/api-keys/
mapView.loadVenue(options:
MPIOptions.Init(
clientId: "5eab30aa91b055001a68e996",
clientSecret: "RJyRXKcryCMy4erZqqCbuB1NbR66QTGNXVE0x3Pg6oCIlUR1",
venue: "mappedin-demo-mall"
),
showVenueOptions: MPIOptions.ShowVenue(multiBufferRendering: true, outdoorView: MPIOptions.OutdoorView(enabled: true), shadingAndOutlines: true))
}

v6 Initialization

// See Trial API key Terms and Conditions
// https://developer.mappedin.com/docs/demo-keys-and-maps
let options = GetMapDataWithCredentialsOptions(
key: "5eab30aa91b055001a68e996",
secret: "RJyRXKcryCMy4erZqqCbuB1NbR66QTGNXVE0x3Pg6oCIlUR1",
mapId: "mappedin-demo-mall"
)
// Load the map data.
mapView.getMapData(options: options) { [weak self] r in
guard let self = self else { return }
if case .success = r {
print("getMapData success")
// Display the map.
self.mapView.show3dMap(options: Show3DMapOptions()) { r2 in
if case .success = r2 {
print("show3dMap success - Map displayed")
} else if case .failure(let error) = r2 {
print("show3dMap error: \(error)")
}
}
} else if case .failure(let error) = r {
print("getMapData error: \(error)")
}
}

Component Access

MPIData.<collection> has been replaced by MapData.getByType(<collection>)

For example:

In v5 access nodes using MPIData.nodes, which contains an array of Node objects.

In v6 access nodes using mapData.getByType<Node>(MapDataType.Node), which returns an array of Node objects.

Mappedin.getCollectionItemById is replaced by mapData.getById(<collection>, id)

The following classes have been redesigned. Refer to the chart below for a mapping of similar classes.

v5 Componentv6 Component
MPIPolygonSpace
MPIMapGroupFloorStack
MPIMapFloor
MPICoordinatesCoordinate
MPINodeNode

MPIState no longer exists.

UI Components

MPIFloatingLabelManager has been replaced with Labels.

MPIFloatingLabelManager.labelAllLocations() will be replaced with MapView.auto().

MPIMarkerManager has been replaced with Markers.

Tooltips have not been carried over from v5 and Markers should be used instead.

Updating UI Components

setPolygonColor, clearPolygonColor and other methods of changing the state of UI objects on the map is now performed using MapView.updateState(), which also supports initial for returning properties to their original state.

MPICameraManager.animate() has been renamed to Camera.animateTo().

MPIMarkerManager.animate() has been renamed to Markers.animateTo().

Interactivity

MapView.addInteractivePolygon() has been replaced by updating the state of each space to be interactive as shown below.

// Set all spaces to be interactive so they can be clicked
mapView.mapData.getByType(.space) { [weak self] (result: Result<[Space], Error>) in
guard let self = self else { return }
if case .success(let spaces) = result {
spaces.forEach { space in
self.mapView.updateState(space: space, state: GeometryUpdateState(interactive: true))
}
}
}

Event names passed from MapView.on() have been changed:

v5 Eventv 6 Event
E_SDK_EVENT.CLICKEvents.click
E_SDK_EVENT.MAP_CHANGED , E_SDK_EVENT.MAP_CHANGED_WITH_REASONEvents.floorChange
E_SDK_EVENT.OUTDOOR_VIEW_LOADEDEvents.outdoorViewLoaded

Stacked Maps

Stacked Maps APIs have been replaced with Multi Floor View along with the ability to control the visibility and altitude of floors. Refer to the Multi Floor View and Stacked Maps guides for more information.

Map Metadata

Classes containing enterprise map metadata have been renamed.

v5 Componentv6 Component
MPICategoryEnterpriseCategory
MPILocationEnterpriseLocation
MPIVenueEnterpriseVenue

Wayfinding & Directions

MapData.getDirections() only supports getting directions between two locations. For multi destination directions, use MapData.getDirectionsMultiDestination().

MPIJourneyManager is now Navigation.

Camera

v5 MPICameraManager.tilt in radians is replaced by v6 Camera.pitch in degrees. Camera.minPitch and Camera.maxPitch are now available to set the minimum and maximum pitch values.

v5 MPICameraManager.rotation in radians is replace in v6 by Camera.bearing in degrees Clockwise rotation is now positive.

v5 Camera.zoom, Camera.minZoom and Camera.maxZoom used meters from ground level. In v6 these now use mercator zoom level units.

The following camera methods and accessors have been renamed.

v5 Methodv6 Method
MPICameraManager.position()Camera.center()
MPICameraManager.setSafeAreaInsets()Camera.setScreenOffsets()
MPICameraManager.safeAreaInsets()Camera.screenOffsets()
MPIMapViewDelegate.onCameraChanged()MapView.on(...)

MPISearchManager has been changed to Search. The results returned in SearchResult are more structured:

struct SearchResult {
let enterpriseCategories: [SearchResultEnterpriseCategory]?
let enterpriseLocations: [SearchResultEnterpriseLocations]?
let places: [SearchResultPlaces]
}

Multi Language

The methods to work with maps in multiple languages have been changed.

v6

// Specify a non default language when getting map data
let options = GetMapDataWithCredentialsOptions(
key: "key",
secret: "secret",
mapId: "mapId",
language: "en"
)

// Get supported languages
mapView.mapData.getByType(.enterpriseVenue) { [weak self] (result: Result<[EnterpriseVenue], Error>) in
guard let self = self else { return }
if case .success(let enterpriseVenue) = result {
enterpriseVenue.languages.forEach { language in
print("Language: \(language)")
}
}
}

// Change language
mapData.changeLanguage("es") { result in
switch result {
case .success:
print("Map language changed to Spanish")
case .failure(let error):
print("Error: \(error)")
}
}

Blue Dot

The Blue Dot system has been redesigned in v6. MPIBlueDotManager has been replaced by BlueDot, accessed through MapView.blueDot. The v6 API provides more granular control over the Blue Dot's appearance, a richer event system and asynchronous result callbacks.

tip

Complete examples demonstrating Blue Dot can be found in the Mappedin iOS GitHub repo:

Class and API Changes

v5 Componentv6 Component
MPIBlueDotManagerBlueDot
MPIOptions.BlueDotBlueDotOptions
MPIPosition / MPICoordinatesBlueDotPositionUpdate
MPIBlueDotManager.setState(state:)BlueDot.follow() with FollowMode
MPIState.FOLLOW / MPIState.EXPLOREFollowMode (.positionOnly, .positionAndHeading, .positionAndPathDirection, nil)

Enabling Blue Dot

In v5, the Blue Dot is enabled through MPIBlueDotManager with minimal options. In v6, BlueDot.enable() accepts BlueDotOptions to customize the appearance and provides an asynchronous result callback.

v5:

mapView?.blueDotManager.enable(options: MPIOptions.BlueDot())

v6:

let options = BlueDotOptions(
accuracyRing: BlueDotOptions.AccuracyRing(color: "#2266ff", opacity: 0.25),
color: "#2266ff",
heading: BlueDotOptions.Heading(color: "#2266ff", opacity: 0.6),
initialState: .inactive,
radius: 12,
watchDevicePosition: false
)

mapView.blueDot.enable(options: options) { result in
if case .success = result {
print("BlueDot enabled")
}
}

Disabling Blue Dot

v6 introduces an explicit BlueDot.disable() method with a result callback.

mapView.blueDot.disable { result in
if case .success = result {
print("BlueDot disabled")
}
}

Updating Blue Dot Position

In v5, positions are provided through MPIPosition containing MPICoordinates. In v6, BlueDotPositionUpdate provides typed parameters for each field and supports partial updates.

v5:

let coords = MPICoordinates(latitude: 43.520124, longitude: -80.539517, accuracy: 2.0, floorLevel: 0)
let position = MPIPosition(timestamp: 1.0, coords: coords)
mapView?.blueDotManager.updatePosition(position: position)

v6:

let position = BlueDotPositionUpdate(
accuracy: .value(5.0),
floorId: .id("floor_id"),
heading: .value(90.0),
latitude: .value(43.520124),
longitude: .value(-80.539517)
)

mapView.blueDot.update(position: position, options: BlueDotUpdateOptions(animate: true)) { result in
if case .success = result {
print("BlueDot position updated")
}
}

Events

v5 relies on MPIMapViewDelegate methods for Blue Dot events. v6 uses an event-based system through BlueDotEvents, which provides more event types including click, error and follow change events.

v5:

func onBlueDotPositionUpdate(update: Mappedin.MPIBlueDotPositionUpdate) {
print(update.position)
}

func onBlueDotStateChange(stateChange: Mappedin.MPIBlueDotStateChange) {
print(stateChange.name)
print(stateChange.reason)
}

v6:

mapView.blueDot.on(BlueDotEvents.positionUpdate) { payload in
guard let payload = payload else { return }
let floorName = payload.floor?.name ?? "nil"
let heading = payload.heading.map { String(format: "%.0f°", $0) } ?? "nil"
print("position-update: (\(payload.coordinate.latitude), \(payload.coordinate.longitude)) floor=\(floorName) heading=\(heading)")
}

mapView.blueDot.on(BlueDotEvents.statusChange) { payload in
guard let payload = payload else { return }
print("status-change: \(payload.status.rawValue) (action: \(payload.action.rawValue))")
}

Camera Follow Mode

In v5, camera follow mode is controlled through MPIState. In v6, MPIState no longer exists and follow mode is controlled directly through BlueDot.follow() with FollowMode options that provide more granular control.

v5:

mapView?.blueDotManager.enable(options: MPIOptions.BlueDot(smoothing: true))
mapView?.blueDotManager.setState(state: MPIState.FOLLOW)

v6:

mapView.blueDot.follow(FollowMode.positionOnly)

Refer to the Blue Dot guide for full documentation on v6 Blue Dot capabilities.