Mapsted Mobile SDK

Current Version: v3.6

iOS Support Minimum Level: iOS 11 Xcode 10 & Swift 4.2


Real Time Positioning

All-In-One Deluxe Lite

Use Mapsted's positioning technology to accurately show user positioning in closed spaces.

User Position

Getting the user position

  1. Register for position change notifications

    MNPositioningApi.shared.registerPositionDelegate(delegate: self)
    
  2. Conform to MNPositionDelegate

    extension <Your Controller>: MNPositionDelegate {
        func onPositionChange(position: MNPosition) {
            //handle updated user position
        }
        //...
    }
    

Support multiple coordinate system

The sdks expect position in Mercator coordinate system - https://en.wikipedia.org/wiki/Mercator_projection. Decimal lat/long can be converted to Mercator using an instantiation method of MNMercator.

- (id)initWithLat:(double)lat lng:(double)lng

Multi-building support

To get all the properties that are available under the license

let propertyInfos = MNPositioningApi.shared.propertyInfos()

To get the buildings inside a property

let propertyInfo = propertyInfos[0]
for buildingInfo in propertyInfo.buildingInfos()  {
    print(buildingInfo.name)
}

To get property info for a specific property by id

let propertyInfo = MNPositioningApi.shared.propertyInfo(propertyId: 212)

To get building info for a specific building by id

let buildingInfo = MNPositioningApi.shared.buildingInfo(buildingId: 104)

Multi-floor support

Getting the floor list by building

let floorInfos = buildingInfo.floorInfos
for floorInfo in floorInfos {
    print(floorInfo.floorName)
}

Property and Building

Downloading property data

// do in background thread
 DispatchQueue.global(qos: .background).async {
    let success = MNPositioningApi.shared.downloadPropertyDataSync(propertyId: 212, language: .english)
    if success {
        //download successful
    }
}

Routing

All-In-One Deluxe

Use our advanced routing technology to show optimal routes to get around selected properties.

Accessibility routing (choose elevator/escalator/stairs)

 RoutingOptionsManager.shared.useStairs = false
 RoutingOptionsManager.shared.useElevators = true
 RoutingOptionsManager.shared.useEscalators = true

Routing in order

Calculates route mainatining the order of destinations.

RoutingOptionsManager.shared.setRouteType(isShortest: false)

Optimized route

Calculates shortest route that visits all the destinations. The order of visit may not be the same as the order of added destinations.

RoutingOptionsManager.shared.setRouteType(isShortest: true)

Multi-destination routing

Multiple destinations are supported in routing. User can set fromCurrentLocation to true to use current location as start of route. If this is false, route is computed starting from the first destination.

RoutingManager.routeRequest(buildingId: Int, destinations: [MNSearchEntity], fromCurrentLocation: Bool)

Get Routing Information

  1. Register for route notifications:

    MNPositioningApi.shared.RoutingDelegate(delegate: MNRoutingDelegate)
    
  2. Conform to MNRoutingDelegate protocol

    extension <Your controller>: MNRoutingDelegate {
        func onRouteResponse(_ response: MNRouteResponse) {
            if response.isSuccessful {
                let routes = response.routes()
                //display route on map
            }
            else {
                print(response.error)
            }
        }
        //...
    }
    

Auto re-routing

The route will be automatically re-calculated in navigation mode and your view controller that subscribes to MNRoutingDelegate will get notified of the new route response.

extension <Your controller>: MNRoutingDelegate {
    func onRouteRecalculation(newRouteResponse: MNRouteResponse) {

    }
    //...
}

Parsing the route

Once a route response is received, call routeCount to get the count of routes and floorCountForCurrentRoute to get the number of floor tansitions for current route. If there is a floor transition, this count will be > 1.

    MNMapApi.shared.routeCount() 
    MNMapApi.shared.floorCountForCurrentRoute()

To switch to a specific route, call

MNMapApi.shared.switchRoute(routeIndex: Int)

To switch to a specific floor for current route, call

MNMapApi.shared.switchFloorForRoute(floorIndex: Int) 

Routing instructions

To get the instructions for the route, call routingInstructions

let routeInstructions = MNMapApi.shared.routingInstructions()
for routeInstruction in routeInstructions {
    print(routeInstruction.instruction)
}

Search/filter by name or category

It is possible to get a list of stores (a.k.a search entity) for a property and then search by name or filter by category.

    guard let propertyData = MNPositioningApi.shared.propertyData(propertyId: propertyId) else {
        return
    }
    if let searchEntities = propertyData.searchEntities()?.searchEntities() {
        for searchEntity in searchEntities {
            print(seachEntity.name)
            print(seachEntity.category)
        }
    }

Mapsted Map

All-In-One Deluxe

The Mapsted Map offers a visual interface powered by Mapsted's technology to not only show user positioning but also display, points of interest, popups, and more.

Setting up the map

In the interface builder, create a view inside your view controller for the map. Resize the view to the size you need. Let the view outlet be named mapPlaceholderView. Inside your view controller class, add MNMapViewController as a child.

let mapViewController = MNMapViewController()

override func viewDidLoad() {
    super.viewDidLoad()
    addChild(mapViewController)
    mapViewController.view.translatesAutoresizingMaskIntoConstraints = false
    mapPlaceholderView.addSubview(mapViewController.view)
    mapViewController.addParentsConstraints()
    mapViewController.didMove(toParent: self)
}

Map interactions

The view controller that has the MNMapViewController as child is automatically set up to receive the map event notifications. It just needs to conform to the MNMapListenerDelegate delegate. When map is panned, onMapMoved will get called. When user taps on the map outside any vector elements, outsideBuildingTapped gets called with the tap position and the tap type.

extension MapViewController: MNMapListenerDelegate {
    func outsideBuildingTapped(mapPos: MNMercator, type: MNMapApi.TapType) {
        DispatchQueue.main.async {
            if type == .eSingle {
                //handle single tap
            }
            else if type == .eLong {
               //handle long tap
            }
            else if type == .eDouble {
                //handle double tap
            }
        }
    }
    func onMapMoved() {
        DispatchQueue.main.async {
            //update UI if required
        }
    }
}

Map vector element interactions

The view controller that has the MNMapViewController as child is automatically set up to receive the map vector element notifications. It just needs to conform to MNMapVectorElementListenerDelegate. The onPolygonClicked gets called when user taps on a vector element on map. The onBalloonClicked gets called when user taps a pop up.

extension MapViewController: MNMapVectorElementListenerDelegate {
    func onPolygonClicked(polygon: MNMapPolygon) {
        //From polygon clicked, get info such as name, centroid etc.

        let centroid = polygon.centroid()
        let name = polygon.name()
    }
    func onBalloonClicked(searchEntity: MNSearchEntity) {
    }
}

Drawing property on the map

Drawing the property (including all buildings):

    guard let propertyData = MNPositioningApi.shared.propertyData(propertyId: propertyId) else {return}
    MNMapApi.shared.drawProperty(isSelected: true, propertyData: propertyData)

Centering map

To simply center the map at a specific location, use:

MNMapApi.shared.mapView()?.moveToLocation(mercator: MNMercator)

To center and update zoom use:

MNMapApi.shared.mapView()?.moveToLocation(mercator: MNMercator, zoom: Float, duration: Float)

Tilting map

Use tiltMap where angle is the desired tilt angle and duration is the duration of the animation in seconds.

MNMapApi.shared.mapView()?.tiltMap(angle: Float, duration: Float)