Places iOS SDK

In this page you can see how to create a geolocation-based augmented reality iOS app using the places SDK.

Creating the Xcode project

We will start creating a new Xcode project. In the project creation window, we will select a single page application template, which will create a basic project structure for our app. You can select other templates depending on the complexity of your application.

Installing the Places SDK dependency

Cocoapods is a dependency manager for Swift and Objective-C Cocoa projects. To install it, you will need to use the Ruby package manager:

$ gem install cocoapod

You may need to use sudo to install the gem if you are using the defualt Ruby install.

Once you have installed cocoapods, you have to create a new Podfile using the following command on your project root directory:

$ pod init

Now, you can install the Places SDK pod with:

$ pod install

Using the SDK

With the pod installed and ready, we can start using it in our application. We will start adding a new view to our main ViewController, which will be showing the camera feed, as well as the augmented reality content. To do so, it's really important that we select the OXMapView custom class for this view in the inspector:

If the OXMapView class doesn't appear in the selector, that means that the pod wasn't installed correctly. Please review the pod installation section to install the pod correctly.

We will also need to link this view to our ViewController using the inspector. Now we just need to call the OXMapView method loadMap inside our ViewController, once the views have been loaded. You can see an example here, which also uses a custom configuration for the map and places:

import OnirixPlacesSDK
import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var mapView: OXMapView!

    private static let PROJECT_KEY: String = "<YOUR_PROJECT_KEY>"
    private static let MAP_OID: String = "<YOUR_MAP_OID>"

    override func viewDidLoad() {
        super.viewDidLoad()
        self.startMap()
    }

    func startMap() {
        do {
            // Configure map parameters
            let mapConfig = try MapConfig()
                .with(visionDistance: 5000)
                .with(showRadar: true)
                .with(radarDistance: 4000)

            // Configure place parameters
            let placeConfig = try PlaceConfig()
                .with(showDistance: true)
                .with(distanceFontColor: UIColor.black)
                .with(distanceBackgroundColor: UIColor.white)
                .with(distancePaddingPixels: 15)
                .withDistanceBorder(pixels: 4, color: UIColor.gray, radius: 3)

            // for now, all places created in Studio have category 'default'
            mapConfig.setConfigForCategory(placeConfig, "default")
            mapView.loadMap(oid: ViewController.MAP_OID, projectKey: ViewController.PROJECT_KEY, mapConfig: mapConfig)

            // [Optional] Provide a map delegate if you want
            mapView.mapDelegate = self
        } catch {
            // in case we insert an invalid map or place configuration
            print("There was an error creating the map configuration: \(error)")
        }
    }
}

As you can see on the sample, we can pass a custom map delegate to our OXMapView that will receive different callbacks from the map view. To do so, the class that we use as delegate must implement the OXMapDelegate protocol, here is an example:

import CoreLocation

extension ViewController: OXMapDelegate {
    func onMapReady(map: Map?, error: String?) {
        print("Map ready!")
    }

    func onLocationUpdate(location: CLLocation) {
        print("Location updated!")
    }

    func onPlaceTouched(place: Place) {
        print("Place touched: \(place)")
    }

    func onFocusChanged(newFocus: PlaceARWrapper?) {
        if let focus = newFocus {
            print("Focus changed: \(focus)")
        } else {
            print("Focus lost!")
        }
    }
}

More information about this map delegate can be seen on the Delegates section.

Map Configuration

The MapConfig class uses a builder pattern with the following methods:

Method Description Default value
with(showRadar: Bool) Sets whether the radar should be shown or not. True
with(radarDistance: Float) Sets the radius (meters) which the radar will draw. 1000
with(visionDistance: Float) Sets the distance (meters) for visible POIs. 1000
with(poiDrawManager: PoiDrawManager) Sets the PoiDrawManager instance that tells the engine how big to draw a POI depending on its distance. POIDrawManager.DEFAULT
with(useElevations: Bool) Sets whether the user's and POI's elevation will be taken into account or not. true
with(useUpdateRadius: Bool) Sets whether to download POIs in a circle centered in the user (true) or all of them (false) false
with(updateRadius: Float) Sets the radius to download POIs. 2000
with(updateRatio: Float) Sets the factor of the radius above when to re-download the area. 0.33

PoiDrawManager

PoiDrawManager is the class in charge of deciding how big each poi is rendered. In order to use custom values, you have to pass a list of PoiDistance to its constructor. Each PoiDistance represents the size at which a point will be drawn at a given distance, being its first parameter the distance and the second its size multiplier (compared to how big you would see it if it was 1 meter away). For example, if you use new PoiDistance(10, 0.5f) and the POI is 10 meters away, you will see it half the size as if it was only a meter away.

Place Configuration

The PlaceConfig class also uses a builder pattern with the following methods:

Method Description Default value
with(font: UIFont) Sets the font that will be used to draw the Place name and distance (if enabled). Futura
with(markerActive: UIImage) Sets the image to represent an active marker (focused by the crosshair). default_marker_active
with(markerInactive: UIImage) Sets the image to represent an inactive marker (not focused by the crosshair). default_marker_inactive
with(showName: Bool) Sets whether the name of the place should be shown or not. true
with(showDistance: Bool) Sets whether the distance to the place should be shown or not. false
with(showMarker: Bool) Sets whether the marker should be shown or not. true
with(nameActiveFontColor: UIColor) Sets the foreground color of the name font when its place is active. 0xFFFFFFDD (RGBA)
with(nameInactiveFontColor: UIColor) Sets the foreground color of the name font when its place is inactive. 0x000000DD (RGBA)
with(nameInactiveBackgroundColor: UIColor) Sets the background color of the name node. 0xFFFFFFDD (RGBA)
with(nameActiveBackgroundColor: UIColor) Sets the background color of the name node when it is active. 0xEE0979DD (RGBA)
withNameBorder(pixels: Float, color: UIColor, radius: Float) Sets the values of the border of the name node. Its pixels (width of the border), its color, and the border radius. 0, 0xFFFFFFFF (RGBA), 30
with(nameHeight: Float) Sets the height of the name node. 0.25
with(namePaddingPixels: Float) Sets the padding pixels between the edge of the name node and the text. 30
with(distanceFontColor: UIColor) Sets the foreground color of the distance text. 0xFFFFFFFF (RGBA)
with(distanceBackgroundColor: UIColor) Sets the background color of the distance node. 0xEE0979DD (RGBA)
with(distancePaddingPixels: Float) Sets the padding pixels between the edge of the distance node and the text. 30
with(distanceHeight: Float) Sets the height of the distance node. 0.15
withDistanceBorder(pixels: Float, color: UIColor, radius: Float) Sets the values of the border of the distance node. Same parameters as withNameBorder. 30, 0xFFFFFFFF (RGBA), 30

A Place configuration must be applied to a PlaceCategory. For that you can use the following method from the MapConfig class: mapConfig.setConfigForCategory(placeConfig, <CATEGORY_NAME>) This category name can be defined from the website editor when creating new places. By default (if not specified) this category name is "default" for every place.

Routes

In order to be able to use routes, you will have to create nodes and ways in your map. After that, you can use the following method: initRoute(key: String, context: OXMapView, config: RouteConfig, destination: PlaceARWrapper) The sdk will then calculate the path from the node closest to you to the destination node closer to the given coordinates and then to the exact coordinates. Keep in mind that if there are no nodes close to you or the destination it may create a weird path.

Route Components

Route components are independent elements that will show information about the route. It is possible to implement your own using the RouteComponent protocol. The default ones are:

RouteHUDComponent

It shows a sign indicating the direction to turn in each node. It can be straight, left or right.

DirectionArrowComponent

It indicates in which direction is the next node by drawing a blinking arrow on your feet.

DestinationIndicationComponent

Displays an animation on the destination node.

RouteConfig

Method Description Default value
with(onRouteStarted: () -> ()) Sets the callback that will be called when the route starts. nil
with(onRouteFinished: (Bool) -> ()) Sets the callback that will be called when the route finishes. nil
with(onRouteRecalculate: () -> ()) Sets the callback that will be called when the route is recalculated. nil
with(recalculationEnabled: Bool) Sets whether route recalculation is enabled or not. true
add(routeComponent: RouteComponent) Adds a new route component. Empty

Route recalculation

If route recalculation is enabled, it detects if the user is walking outside the path and will try to recalculate the whole route in order to find a shorter path.

Delegates

OXMapDelegate

Method to implement Description
onMapLoaded(map: Map?, error: String?) Called when the map is loaded. If there is any problem, map will be nil and an error message will be sent.
onLocationUpdate(location: CLLocation) Called when a new user location is received.
onPlaceTouched(place: Place) Called whenever a place is touched, with the touched place as a parameter.
onFocusChanged(newFocus: PlaceARWrapper?) Called whenever a place enters or exits the crosshair on the center of the screen. If the focus is lost (place exits the crosshair), then newFocus will be nil.