## version-5.0 ### API Reference # API Reference ## Latest Version Mappedin SDK for iOS v5.8.2 ## Previous Versions v5.8.1v5.8.0v5.7.0v5.6.1v5.6.0v5.5.0v5.4.0v5.3.1v5.3.0v5.2.1v5.2.0v5.1.9v5.1.8v5.1.7v5.1.6v5.1.5v5.1.4v5.1.3v5.1.2v5.1.1v5.1.0v5.0.4v5.0.3v5.0.0v5.0.0-beta.7v5.0.0-beta.0 ### Blue Dot # Blue Dot > Displaying user position inside a building is not accurate with just GPS. However, there are a multitude of Indoor Positioning Systems utilizing different technological approaches to providing an accurate and reliable positioning inside. Mappedin works with any IPS capable of providing the SDK with latitude, longitude and floor level information. > A complete class that uses the code snippets in this guide can be found in the Mappedin iOS Github repo: BlueDotVC.swift ## Enabling Blue Dot You can initialize and enable the Blue Dot when the map first loads by using the onFirstMapLoaded/>) function implemented by MPIMapViewDelegate. The MPIBlueDotManager can be easily enabled with default settings by calling `mapView.blueDotManager.enable(MPIOptions.BlueDot())`. There are two useful events to listen to: position update and state change. For debugging purposes, you could add print statements to the following functions. Position updates could be useful for reacting to a user entering or leaving a certain radius of a store. Status updates help handle situations where the position is no longer available. ```swift func onFirstMapLoaded() { mapView?.blueDotManager.enable(MPIOptions.BlueDot()) } func onBlueDotPositionUpdate(update: Mappedin.MPIBlueDotPositionUpdate) { print(update.position) } func onBlueDotStateChange(stateChange: Mappedin.MPIBlueDotStateChange) { print(stateChange.name) print(stateChange.reason) } ``` ## Simulating Blue Dot To display a Blue Dot with the SDK, you'll need the position information in the form of MPICoordinates. The following is a point in the fictional Mappedin Demo Mall with an accuracy of 2 meter radius on the floor level `0`. ```swift let coords = MPICoordinates(latitude: 43.52012478635707, longitude: -80.53951744629536, accuracy: 2.0, floorLevel: 0) ``` Using our sample coordinate, we can draw the Blue Dot on the map by creating an `MPIPosition` and passing it to `blueDotManager.updatePosition()`. ```swift func onFirstMapLoaded() { mapView?.blueDotManager.enable(options: MPIOptions.BlueDot()) let coords = MPICoordinates(latitude: 43.52012478635707, longitude: -80.53951744629536, accuracy: 2.0, floorLevel: 0) let position = MPIPosition(timestamp: 1.0, coords: coords) mapView?.blueDotManager.updatePosition(position: position) } ``` !iOS Blue Dot > Note: A complete class that uses the code snippets in this guide can be found in the Mappedin iOS Github repo: BlueDotVC.swift ## Blue Dot Display States - When the Blue Dot position given to Mappedin JS has a high accuracy (within a few meters) and is on the floor currently displayed, it is displayed as bright blue. !Blue Dot - Accurate - If the Mappedin Blue Dot is able to detect that a given position update is inaccurate, a semi-transparent blue shadow is displayed underneath the Blue Dot to indicate uncertainty range. !Bluedot Inaccurate - When the BlueDot is on another floor it will look semi-transparent. !Blue Dot - Accurate on another floor - The uncertainty range is shown also when displaying the Blue Dot on another floor than the currently viewed one. !Blue Dot Inaccurate on another floor - 30 seconds after the latest position update, the BlueDot is displayed as greyed out as it's possible that the user has moved but no updates have been received. !Blue Dot - Outdated ## Wayfinding From Blue Dot A common map feature is to provide a user with directions from their current location. Mappedin JS is able to provide the nearest node to the user's location, which can be used as the starting point for wayfinding. Pass the user's destination to the `getDirections` method to create a directions object that can be used to draw the path. ```swift func onBlueDotPositionUpdate(update: Mappedin.MPIBlueDotPositionUpdate) { let destination = mapView?.venueData?.locations.first(where: { $0.name == "Destination Name" }) mapView?.getDirections(to: destination!, from: update.nearestNode!) { directions in self.mapView?.journeyManager.draw(directions: directions!) } } ``` > A complete class that uses the code snippets in this guide can be found in the Mappedin iOS Github repo: BlueDotVC.swift ## Camera Follow Mode In some instances, a user may pan the camera away and lose track of their own Blue Dot position. An app may want to snap the camera to the user's location to reorient themselves. While this could also be done using camera controls, an app can also leverage the map STATE to pin the camera to the Blue Dot's location. By default, the map starts in EXPLORE mode allowing the user to freely control the camera position. To pin the camera to the Blue Dot, set the camera state to FOLLOW with Blue Dot enabled. ```swift mapView?.blueDotManager.enable(options: MPIOptions.BlueDot(smoothing: true)) mapView?.blueDotManager.setState(state: MPIState.FOLLOW) ``` The camera will animate to the Blue Dot position whenever it is updated, however, it doesn't zoom or rotate. When providing wayfinding directions, it may be beneficial to orient the camera along the route. Enable this by setting useRotationMode of MPIOptions.BlueDot to true to when calling MPIBlueDotManager.enable()/>). > Rotation mode only works when using the MPIJourneyManager. The camera will not rotate with a path created using MPIPathManager. You can read more about path differences in the Wayfinding guide. ```swift mapView?.blueDotManager.enable( options: MPIOptions.BlueDot(smoothing: true, useRotationMode: true)) mapView?.blueDotManager.setState(state: MPIState.FOLLOW) ``` ## Additional Reading - Indoor Positioning Made Easy with Apple's Core Location for iOS ### Building & Level Selection # Building & Level Selection > This guide demonstrates how to populate menus with Mappedin venue data to create a building and level selector. This will allow listing of all buildings, the levels of each building and the ability to switch between them. !Building & Level Selection - iOS v5 > Note: A complete class that uses the code snippets in this guide can be found in the Mappedin iOS Github repo: LevelSelectorVC.swift The `populateBuildingMenu` below populates a menu with the names of MPIMapGroups (buildings) used by the `buildingButton`. `populateBuildingMenu` can be called after the MPIMapViewListener.onDataLoaded/>) method has fired, which indicates the venue data has been loaded and is ready to be used. The UIActions update the `buildingButton` title with the chosen MPIMapGroup and call populateLevelMenu to load all of the MPIMap.names (levels) in the `levelButton` menu. ```swift // Populates the Building Selection menu with all Map Groups. func populateBuildingMenu() -> UIMenu { var menuActions: [UIAction] = [] // Loop through all map groups and add their name to the building selection menu. mapView?.venueData?.mapGroups.forEach{mapGroup in let buildingAction = UIAction(title: mapGroup.name ?? "Unknown") { (action) in // When a building is selected from the menu, change the button title and trigger loading of all // map names (levels) in the map group into the level selection menu. print(mapGroup.name ?? "Unknown" + " was clicked") self.buildingButton.setTitle(mapGroup.name, for: .normal) self.levelButton.menu = self.populateLevelMenu(selectedBuilding: mapGroup.name ?? "Default") self.mapView?.setMap(map: mapGroup.maps[0]) self.levelButton.setTitle(mapGroup.maps[0].name, for: .normal) } menuActions.append(buildingAction) } return UIMenu(title: "Choose a Building", options: .displayInline, children: menuActions); } ``` The `populateLevelMenu` is called to populate the menu for the `levelButton`. The `levelButton` menu must be populated on first load after MPIMapViewListener.onDataLoaded/>) has fired and updated when a new map group is selected. `populateLevelMenu` is called from within the UIActions of each map group (building). The following code shows using UIActions to create a menu for the `levelButton` with all MPIMap.names (buildings). When a map name is chosen from the menu, the UIAction fires, updating the levelButton title and loading the chosen map. ```swift // Populates the Level Selection menu with all Map names in the selected building (Map Group). func populateLevelMenu (selectedBuilding:String) -> UIMenu { var menuActions: [UIAction] = [] // Loop through all maps and add their name to the level selection menu. mapView?.venueData?.mapGroups.first(where: {$0.name == selectedBuilding})?.maps.forEach{map in let levelAction = UIAction(title: map.name) { (action) in // When a new level is selected, change the button title and display the chosen map. print(map.name + " was clicked") self.levelButton.setTitle(map.name, for: .normal) self.mapView?.setMap(map: map) } menuActions.append(levelAction) } return UIMenu(title: "Choose a Level", options: .displayInline, children: menuActions); } ``` > Note: A complete class that uses the code snippets in this guide can be found in the Mappedin iOS Github repo: LevelSelectorVC.swift ### Callbacks # Callbacks > The Mappedin Mobile SDKs offer callback functions that developers can use to trigger various events based on the completion of certain actions. These methods are useful for modifying UI elements such as loading views, changing floors, changing polygon colours, adding markers etc. An `MPIMapViewDelegate` will respond to events triggered by the `MPIMapView`. To listen to these events, create or modify a class to fit the `MPIMapViewDelegate` protocol and implement the methods you'd like to use. They will be executed automatically after the corresponding event has occurred. ## onDataLoaded A callback function that is executed when the 3D files have been downloaded for the first map, and are starting to load into memory. The `MPIMapView` is fully functional at this point, but some things will still be popping in. At this point, you can interact with the `MPIMapView`, venue data, call helper functions, call other mapView functions, and set up your application. This function will pass in an `MPIData` parameter, `data`, which allows you to use maps, locations, polygons, nodes, vortexes, and map groups of the venue. For example, you can access the list of a venue’s locations by using the class variable locations of the `data` parameter. You can also call other `mapView` functions here. For example, you can label your polygons by calling `labelPolygon` and passing in both an `MPIPolygon` parameter and various customization options for your labels. ## onFirstMapLoaded A callback that is executed when the first map is fully loaded. This means `onDataLoaded` has already been fired (if specified) and all the textures and other resources have finished popping in. ## onMapChanged A callback function that is executed when the map of your `MPIMapView` changes. A common use of this callback is to add a level selector for your venue. If you are working with a venue that has multiple maps (such as a venue with multiple floors) you may want to create a dropdown to allow the user to select a level. When you change the map, this callback will be executed, and it will pass in an `MPIMap` parameter, `map`, which is the current map. You can access different properties of `map` using this parameter. ## Sample Code ```swift extension ViewController: MPIMapViewDelegate { func onBlueDotPositionUpdate(update: MPIBlueDotPositionUpdate) { // Called when the blueDot that tracks the user position is updated } func onBlueDotStateChange(stateChange: MPIBlueDotStateChange) { // Called when the state of blueDot is changed } func onMapChanged(map: MPIMap) { // Called when the map is changed } func onPolygonClicked(polygon: MPIPolygon) { // Called when the polygon is clicked } func onNothingClicked() { // Called when a tap doesn't hit any spaces } func onDataLoaded(data: MPIData) { // Called when the mapView has finished loading both the view and venue data } func onFirstMapLoaded() { // Called when the first map is fully loaded } func onStateChanged (state: MPIState) { // Called when the state of the map has changed } } ``` ### Camera Controls # Camera Controls > To create rich experiences on top of the Mappedin SDK for iOS, it's useful to be able to control the map view programmatically. This guide shows how to focus the map view on targets, how to listen to camera events and how to control the camera. > Note: A complete class that uses the code snippets in this guide can be found in the Mappedin iOS Github repo: CameraControlsVC.swift ## Focus the Camera on Targets To focus on a polygon after it has been touched, we use the `onPolygonClicked()` function in the MPIMapViewDelegate. In this case, we are targeting only the touched polygon. However, we can also give coordinates or nodes as MPIOptions.CameraTargets. ```swift func onPolygonClicked(polygon: MPIPolygon) { mapView?.cameraManager.focusOn(targets: MPIOptions.CameraTargets(polygons: [polygon])) } ``` ## Listening to Camera Events We can use the `onCameraChanged()` function in the MPIMapViewDelegate to monitor changes to the camera position, rotation, tilt, and zoom. ```swift func onCameraChanged(cameraChange: Mappedin.MPICameraTransform) { print("Position \(cameraChange.position)") print("Rotation \(cameraChange.rotation)") print("Tilt \(cameraChange.tilt)") print("Zoom \(cameraChange.zoom)") } ``` ## Controlling the Camera Controlling the camera to set it to a specific tilt, rotation or zoom can be done with `mapView.cameraManager.set()` and configured MPIOptions.CameraConfiguration. Tilt and rotation are set as radians, where as zoom is in the camera distance in meters from the target. ```swift mapView?.cameraManager.set( cameraTransform: MPIOptions.CameraConfiguration( zoom: 1234, tilt: 0.3, rotation: 1.5 ) ) ``` It is possible to limit the tilting of the camera by listening to the change event and setting it to a desired value in `onCameraChanged()`. ```swift func onCameraChanged(cameraChange: Mappedin.MPICameraTransform) { let tilt = 0.0 if(cameraChange.tilt != tilt) { mapView?.cameraManager.set(cameraTransform: MPIOptions.CameraConfiguration(tilt: tilt)) } } ``` If you want to be able to zoom in closer than the default limit, use the setter `mapView?.cameraManager.setMinZoom(zoomLevel: 200.0)`>). ## Animation The camera can also be animated to zoom, tilt and rotate to a MPINode or MPIMap.MPICoordinate. This works similar to the set methods described in the Controlling the Camera section above but instead of jumping directly to a camera position, the camera moves gradually to the new position. The MPICameraManager.animate() methods are use to accomplish this. Animating to the node of a location: ```swift let zoomTarget = mapView?.venueData?.locations.first( where: { $0.name == "Sunglass Hut" }) let cameraTransform = MPIOptions.CameraTransformNode( zoom: 50.0, tilt: 2.0, rotation: 180.0, position: zoomTarget?.nodes?.first) let cameraAnimation = MPIOptions.CameraAnimation( duration: 3000.0, easing: MPIOptions.EASING_MODE.EASE_IN) mapView?.cameraManager.animate( cameraTransform: cameraTransform, options: cameraAnimation) ``` Animating to latitude and longitude coordinates: ```swift let zoomCoordinate = mapView?.currentMap?.createCoordinate( latitude: 43.86147923972817, longitude: -78.94671703394187) let cameraTransform = MPIOptions.CameraConfiguration( zoom: 50.0, tilt: 2.0, rotation: 180.0, position: zoomCoordinate) let cameraAnimation = MPIOptions.CameraAnimation( duration: 3000.0, easing: MPIOptions.EASING_MODE.EASE_IN) mapView?.cameraManager.animate( cameraTransform: cameraTransform, options: cameraAnimation) ``` ## Reset Camera To reset the camera, store the initial camera position in the onFirstMapLoaded()/>) method. Then, at a later time these values can be used to reset the camera. ```swift // Store the default camera values when the map is loaded. func onFirstMapLoaded() { defaultTilt = mapView?.cameraManager.tilt defaultZoom = mapView?.cameraManager.zoom defaultRotation = mapView?.cameraManager.rotation defaultPosition = mapView?.cameraManager.position } // Use the default camera values to reposition the camera. func resetCamera() { mapView?.cameraManager.set(cameraTransform: MPIOptions.CameraConfiguration( zoom: defaultZoom, tilt: defaultTilt, rotation: defaultRotation, position: defaultPosition)) } ``` > Note: A complete class that uses the code snippets in this guide can be found in the Mappedin iOS Github repo: CameraControlsVC.swift ### Flat Labels # Flat Labels > FlatLabels are painted on the polygon and fill the available space. They automatically flip to always face toward the camera. > Note: A complete class that uses the code snippet in this guide can be found in the Mappedin iOS Github repo: FlatLabelsVC.swift Flat labels can be added with default styles using MPIMapView.flatLabelsManager.labelAllLocations()/>). This call should be made after MPIMapViewListener.onFirstMapLoaded/>) is called, which indicates that the first map is loaded and can be modified. Note that Floating Labels are enabled by default. Floating Labels should be disabled using MPIOptions.ShowVenue options before enabling Flat Labels. Flat Labels can be added and removed all at once as mentioned above or individually using the MPIFlatLabelManager.add()/>) and MPIFlatLabelManager.remove()/>) methods. ## Styling Options Flat Labels are highly customizable, allowing control of size, color and spacing of each label. Flat Label Appearance - MPIOptions.FlatLabelAppearance - `height` is the upper bounds of the Polygon by default. Height can be set if not using a Polygon or a custom height is desired. - `margin` is the amount of space to leave before starting the text from the edge of the bound of the canvas bound. These bounds are set in the Mappedin CMS. The default value is 5 pixels. - `color` is a string format of a hexadecimal color representation, such as `#ff00000` for red. - `fontSize` in pixels, by default 12 - `scaleMin` sets the minimum percentage to shrink the label to if it won't fit within the bounds at 100%. If it doesn't fit at that level, it won't be created. - `scaleStep` describes how much to decrement the scale each time it doesn't fit, so the map doesn't end up with too many different font sizes on screen at once. If only labelling a few Polygons rather than everything, set this and scaleMin to 0.1 to attempt to fit all text. The default value is 0.25. ```swift let flatLabelAppearance = MPIOptions.FlatLabelAppearance(color: "#0a0dbf", fontSize: 8) let flatLabelLocations = MPIOptions.FlatLabelAllLocations(appearance: flatLabelAppearance) mapView?.flatLabelManager.labelAllLocations(options: flatLabelLocations) ``` > Note: A complete class that uses the code snippet in this guide can be found in the Mappedin iOS Github repo: FlatLabelsVC.swift ### Floating Labels # Floating Labels > Map geometry alone is not enough to have a sense of a location. Adding labels to show the names of locations and other points of interest can help users navigate a space. > Note: A complete class that uses the code snippets in this guide can be found in the Mappedin iOS Github repo: FloatingLabelsVC.swift FloatingLabels anchor to polygon entrance nodes and automatically handle rotation and repositioning when the camera moves. Floating Labels are enabled by default with default styling. When customizing Floating Labels, disable them from appearing on startup in MPIOptions.ShowVenue options. Floating Labels can be added to the map by calling mapView.floatingLabelManager.labelAllLocations()/>) is called, which indicates that the first map is loaded and can be modified. Floating Labels can be added and removed all at once as shown above or individually using the MPIFloatingLabelManager `add` and `remove` methods. ## Styling Options Floating Labels are highly customizable, allowing control of size, color, spacing and the ability to display both a Marker (icon) and text in each label. MPIOptions.FloatingLabelAppearance.Margin - `margin` in pixels around the label and marker. This will affect label density. Marker Appearance - MPIOptions.FloatingLabelAppearance.Marker - `backgroundColor` & `foregroundColor` - The marker takes both active and inactive variants of its foreground and background colors. - `size` of the marker in pixels. - `icon` is the SVG of the icon to place inside the Floating Label. - `iconVisibilityThreshold` defines when the icon becomes visible relative to the current zoom level. Values should be between 0 and 1. 0 appears at maximum zoom and 1 causes the marker to always be shown. Text Appearance - MPIOptions.FloatingLabelAppearance.Text - `foregroundColor` and `backgroundColor` can be set using CSS colors, as Hex strings or the CSS name of a color such as crimson. - `maxWidth` defines the maximum width of text in pixels. - `numLines` sets the maximum number of lines to display if the text spans multiple lines. - `size` is the text size in pixels. The code snippet below creates a MPIOptions.FloatingLabelAppearance.Text to set the text color and the maximum number of lines to 2. ```swift let floatingLabelAppearance = MPIOptions.FloatingLabelAppearance( text: MPIOptions.FloatingLabelAppearance.Text(numLines: 2, foregroundColor: "#DAA520", backgroundColor: "#000000")) let styleOptions = MPIOptions.FloatingLabelAllLocations(appearance: floatingLabelAppearance) mapView?.floatingLabelManager.labelAllLocations(options: styleOptions) ``` ## Adding Icons Icons can be added to Floating Labels to highlight certain categories or to make locations more eye-catching. These icons automatically adjust, becoming visible as the user zooms the map to view more detail. The supplied icon must be an SVG image and is provided to MPIOptions.FloatingLabelAppearance.Marker. Note that the SVG must be encapsulated using triple double quotes (“””SVG”””) to avoid double escaping characters within the string. ```swift let svgIcon: String = """ """ let foreGroundColor = MPIOptions.FloatingLabelAppearance.Color( active: "#BF4320", inactive: "#7E2D16") let backgroundColor = MPIOptions.FloatingLabelAppearance.Color( active: "#FFFFFF", inactive: "#FAFAFA") let markerAppearance = MPIOptions.FloatingLabelAppearance.Marker( foregroundColor: foreGroundColor, backgroundColor: backgroundColor, icon: svgIcon ) let markerTheme = MPIOptions.FloatingLabelAppearance(marker: markerAppearance) let styleOptions = MPIOptions.FloatingLabelAllLocations(appearance: markerTheme) mapView?.floatingLabelManager.labelAllLocations(options: styleOptions) ``` ## Preset Themes The Mappedin SDK for iOS provides two preset Floating Label themes that can be easily applied to a map. They are lightOnDark and darkOnLight. These two contrasting themes provide options for both light and dark maps. _Applying the lightOnDark Theme_ ```swift let styleOptions = MPIOptions.FloatingLabelAllLocations( appearance: MPIOptions.FloatingLabelAppearance.lightOnDark) mapView?.floatingLabelManager.labelAllLocations(options: styleOptions) ``` _Applying the darkOnLight Theme_ ```swift let styleOptions = MPIOptions.FloatingLabelAllLocations( appearance: MPIOptions.FloatingLabelAppearance.darkOnLight) mapView?.floatingLabelManager.labelAllLocations(options: styleOptions) ``` > Note: A complete class that uses the code snippets in this guide can be found in the Mappedin iOS Github repo: FloatingLabelsVC.swift ### Getting Started # Getting Started > Mappedin SDK for iOS helps you deliver the rich indoor mapping experience of your venue, designed in Mappedin CMS, inside your iOS apps. In this overview, we will go through the basic concepts that will help you understand how the SDK works. In further sections, we'll also go through the setup and usage of the Mappedin SDK for iOS. The Mappedin SDK for iOS is a native interface to Mappedin JS. The SDK is a framework built using Swift, and it automatically handles any authentication, network communication, fetching of map data, its display, and basic user interaction, such as panning, tapping, and zooming. The SDK allows you to build your own interactions. You can render your own additional layers on top of the map that the SDK renders. > Mappedin SDK for iOS is supported on iOS versions 14.0 and above ## Concepts - After the quick initial setup and configuration, the SDK renders the maps associated with the keys provided by you, inside an MPIMapView instance you created. - The SDK allows you to render your venue's maps in 3D. The SDK pulls the most up-to-date data from our mapping CMS for all your points of interest within your venue. - The SDK supports drawing navigation paths and providing instructions to and from any point of interest within the venue. Both accessible and non-accessible optimized routes are supported. You can build more functionality on top of this experience, such as searching or switching venues. Further pieces of this guide give you more details about how to set up the SDK and customize it as per your liking. ## Coding with AI Mappedin SDK for iOS provides an llms-mappedin-ios.txt file that can be used to help with coding when using Large Language Models (LLMs). ## Quickstart This quickstart guide is written for a new Storyboard application that has been initialized with Cocoapods. ## Add dependency to CocoaPods Mappedin's SDK is available through CocoaPods. You can find the latest version on Github. To install it, add the dependency to your Podfile in your project's root directory: `pod 'MappedIn', '5.8.2'` > For more information on how to use Cocoapods, see here. In order for your project to recognize the Pods framework, you must be working from the `.xcworkspace` file rather than the individual `.xcproj` file. If you started a new project from scratch in Xcode, you'll need to close it and open the workspace. Make sure `platform :ios, '11.0'` is set to version 11.0 at minimum. Your `Podfile` should now have at least the following information with your own app name replacing `mappedin-ios-sdk-app`: ```ruby title=Podfile platform :ios, '11.0' target 'mappedin-ios-sdk-app' do use_frameworks! pod 'MappedIn', '5.0.3' end ``` In the terminal, run `pod install` in your project's root directory. To import the module into the project, add the following line to your `ViewController`: ```swift import Mappedin ``` > Refer to our Github repository to view the sample app created by Mappedin developers to understand how to embed a map into your app. ## Display the Venue ### Creating the MPIMapView instance Now we are ready to initialize an MPIMapView instance `mapView` in the `viewDidLoad()` method of your `ViewController` and add it to the layout: ```swift title=ViewController.swift var mapView: MPIMapView? override func viewDidLoad() { super.viewDidLoad() // Set up MPIMapView and add to view mapView = MPIMapView(frame: view.frame) if let mapView = mapView { self.view.addSubview(mapView) } } ``` ### Load the Venue `loadVenue` is a `MPIMapView` function that allows you to render the venue in your app by passing in an `options` object and an optional `showVenueOptions` object. The required properties of `options` object are `venue`, `clientId`, `clientSecret`. To get you started, we’ve provided a Mappedin id and secret that has access to some demo venues. When you’re ready to start using your own venues with the SDK, you will need to contact a Mappedin representative to get your own unique id and secret. | Property | Value | | -------------- | --------------------------------------------------------------------------- | | `venue` | `mappedin-demo-mall` | | `clientId` | See Here | | `clientSecret` | See Here | You can also pass in MPIOptions.ShowVenue to modify the properties of the map such as the background color, the map that is displayed first and whether all locations are labeled on initialization. Add the following `mapView.loadVenue` call inside the optional unwrapping of `mapView`. ```swift title=ViewController.swift mapView.loadVenue(options: MPIOptions.Init( clientId: "5eab30aa91b055001a68e996", clientSecret: "RJyRXKcryCMy4erZqqCbuB1NbR66QTGNXVE0x3Pg6oCIlUR1", venue: "mappedin-demo-mall"), showVenueOptions: MPIOptions.ShowVenue( labelAllLocationsOnInit: true, backgroundColor: "#ffffff" )) ``` To display the data in an alternative language present in the Mappedin system, you can request the data with custom headers: ```swift MPIOptions.Init( clientId: "5eab30aa91b055001a68e996", clientSecret: "RJyRXKcryCMy4erZqqCbuB1NbR66QTGNXVE0x3Pg6oCIlUR1", venue: "mappedin-demo-mall", headers: [MPIHeader(name: "Accept-Language", value: "en")] ) ``` ### Showing cached venue data `showVenue` is an alternative method to load the venue without using any API calls to retrieve the data. Instead, the data must be passed into the `showVenue` method which takes in a data string (which can be retrieved from a file). > Use this sample JSON file to get started with the `showVenue` method. Here is an example: ```swift // use showVenue to load venue if let path = Bundle.main.path(forResource: "mappedin-demo-mall", ofType: "json") { venueDataString = try? String(contentsOfFile: path) if let venueDataString = venueDataString { mapView.showVenue( venueResponse: venueDataString, showVenueOptions: MPIOptions.ShowVenue(labelAllLocationsOnInit: true, backgroundColor: "#CDCDCD") ) } } ``` ## Result ```swift title=ViewController.swift import UIKit import Mappedin class ViewController: UIViewController { var mapView: MPIMapView? override func viewDidLoad() { super.viewDidLoad() mapView = MPIMapView(frame: view.frame) if let mapView = mapView { self.view.addSubview(mapView) mapView.loadVenue(options: MPIOptions.Init( clientId: "5eab30aa91b055001a68e996", clientSecret: "RJyRXKcryCMy4erZqqCbuB1NbR66QTGNXVE0x3Pg6oCIlUR1", venue: "mappedin-demo-mall"), showVenueOptions: MPIOptions.ShowVenue( labelAllLocationsOnInit: true, backgroundColor: "#ffffff" )) } } } ``` You should see something that looks like this: !iOS SDK v5 - quickstart ### Interactivty # Interactivty > The MPIMapClickDelegate protocol enables an app to receive an MPIMapClickEvent, which include the objects that were clicked. The MPIMapClickEvent includes the following properties, which describe the click event. - Floating Label - Map - Blue Dot - Path - Polygon - Position In order to use MPIMapClickDelegate, it must be added to an MPIMapView. ```swift mapView?.mapClickDelegate = self ``` > Note: A complete class that uses the code snippets in this guide can be found in the Mappedin iOS Github repo: AddingInteractivityVC.swift ## Floating Labels To allow floating labels to be clicked, they must be set to be interactive. ```swift mapView?.floatingLabelManager.labelAllLocations( options: MPIOptions.FloatingLabelAllLocations(interactive: true)) ``` When clicked, the MPIMapClickEvent provides an array of MPIMapClickEvent.FloatingLabelClicked of all floating labels that were clicked. The array contains the floating label's location as an MPINode and it's text as a String. The code sample below checks if the floating label array is empty and if not, appends the text of the first floating label clicked to `message`. ```swift func onClick(mapClickEvent: Mappedin.MPIMapClickEvent) { var message = "" if (!mapClickEvent.floatingLabels.isEmpty) { message.append("Floating Label Clicked: ") message.append(mapClickEvent.floatingLabels.first?.text ?? "") message.append("\n") } } ``` ## Maps MPIMapClickEvent includes an array of MPIMaps corresponding to every map that a user's click passed through. These are in order of first to last intersected. For example, if the user clicked on a map showing the second floor of a building, the second floor map would be first in the array followed by the first floor. The code sample takes the first map in the array and stores the first map's name in a variable called `title`. ```swift func onClick(mapClickEvent: Mappedin.MPIMapClickEvent) { let title = mapClickEvent.maps.first?.name ?? "" } ``` ## Blue Dot MPIMapClickEvent contains a boolean value that is set to true if the user clicked on or near the Blue Dot representing their current location. The code sample below demonstrates detecting if the user clicked near the Blue Dot. ```swift func onClick(mapClickEvent: Mappedin.MPIMapClickEvent) { if (mapClickEvent.nearBlueDot) { // The user clicked near the Blue Dot. } } ``` ## Paths MPIMapClickEvent includes a list of paths the user clicked on. Multiple paths are included if the user clicked on a junction where paths cross. These are in order of first to last intersected by the click point and will be empty if no paths were clicked. When drawing a path, MPIOptions.Path must be used to enable a path to be clickable by setting interactive to true. This applies when using both MPIJourneyManager and MPIPathManager. ```swift // Creating a clickable path using MPIJourneyManager let journeyOpt = MPIOptions.Journey(pathOptions: MPIOptions.Path(interactive: true)) self.mapView?.journeyManager.draw(directions: directions, options: journeyOpt) // Creating a clickable path using MPIPathManager self.mapView?.pathManager.add(nodes: directions.path, options: MPIOptions.Path(interactive: true)) ``` The code sample below detects if the user clicked on an interactive path. ```swift func onClick(mapClickEvent: Mappedin.MPIMapClickEvent) { var message = "" if (!mapClickEvent.paths.isEmpty) { message.append("You clicked a path.\n") } } ``` ## Polygons MPIMapClickEvent provides a list of MPINavigatable.MPIPolygons that the user's click event passes through. These are in order of first to last intersected and will be empty if no polygons were clicked. The code sample below detects if a polygon was clicked and if it was, appends the location name of the polygon to `message`. ```swift func onClick(mapClickEvent: Mappedin.MPIMapClickEvent) { var message = "" if (!mapClickEvent.polygons.isEmpty) { message.append("Polygon clicked: ") message.append(mapClickEvent.polygons.first?.locations?.first?.name ?? "") message.append("\n") } } ``` ## Position / Coordinates MPIMapClickEvent can be used to determine the exact point on the map where the user clicked by observing the MPIMap.MPICoordinate it contains. The `MPICoordinate's` properties provide the x and y coordinates and latitude and longitude of the user's click. The code sample below illustrates how to extract the `MPICoordinate` values from `MPIMapClickEvent` and append them to `message`. ```swift func onClick(mapClickEvent: Mappedin.MPIMapClickEvent) { var message = "" message.append("Coordinate Clicked: \nLatitude: ") message.append(mapClickEvent.position?.latitude.description ?? "") message.append("\nLongitude: ") message.append(mapClickEvent.position?.longitude.description ?? "") } ``` > Note: A complete class that uses the code snippets in this guide can be found in the Mappedin iOS Github repo: AddingInteractivityVC.swift ### Locations # Locations > An MPILocation represents a specific area of interest such as a store location, meeting room or washroom. They contain a rich amount of metadata about a location such as a its name, description, operating hours, logo, phone number and more. > A complete class that uses the code snippet in this guide can be found in the Mappedin iOS Github repo: ListLocations.swift An MPILocation's MPINodes and MPIPolygons can be on multiple MPIMaps, or in multiple non-adjacent places on the same `MPIMap`. For example, all washrooms at a given venue could belong to one `MPILocation`. A washroom location might a have a few `MPIPolygons` spread throughout the venue for each washroom that exists. On the other hand, a department store could live on multiple floors. A single store can just have one presence, and therefore one MPIPolygon. Some Locations have a single point with `MPINodes`. ## Location Types Each location has a single MPILocation.type, which allows filtering or grouping locations of interest to the user. Location types can be unique for each venue. For example a mall may use types of amenity, landmark and tenant. A stadium could use gate, seat and restaurant. An office could use desk, meeting room and washroom. ## Location Categories Each location has 0 to many MPILocation.categories. Categories provide another way to filter and group locations. Location categories are also unique for each venue. Examples of categories for a mall could be Clothing, Electronics, Footwear and Food & Drink. ## Code Sample The code sample below retrieves all locations for a venue, filters those that have a type of tenant, a description, a small logo and sorts them alphabetically by name. ```swift // sortedLocations is an array of MPILocations sortedLocations = mapView?.venueData?.locations.filter { $0.type == "tenant" && // Filter locations with a type of tenant. $0.description != nil && // Filter locations with a description. $0.logo?.small != nil // Filter locations with a small logo. } ?? .init() sortedLocations.sort { $0.name < $1.name } ``` > A complete class that uses the code snippet in this guide can be found in the Mappedin iOS Github repo: ListLocations.swift ### Markers # Markers > The Mappedin SDK for iOS allows adding custom markers to the map. These are elements containing arbitrary HTML that the SDK will anchor to an MPINode on the map, and automatically handle rotation and repositioning to face the camera. > Note: A complete class that uses the code snippets in this guide can be found in the Mappedin iOS Github repo: MarkersVC.swift ## Drawing Markers The createMarker methods of the MPIMapView allows an app to draw a marker at a specified map node or coordinate. An app can draw a marker when a user taps on a polygon using the `onPolygonClick` function exposed by the MPIMapViewDelegate. Get the polygon entrance node from the touched polygon to position the marker and pass this to the `createMarker` method. It is also possible to access the polygon's location to display the location name in the `contentHtml`. ```swift func onPolygonClicked(polygon: MPIPolygon) { guard let location = polygon.locations?.first else { return } guard let entrance = polygon.entrances?.first else { return } mapView?.createMarker( node: entrance, contentHtml: "