Location Tracking

Tutorial by Ranen Ghosh

This tutorial will show you how to track your location on the globe or map. The basic functionality is showing a pulsing marker at your location, with a direction arrow if heading is available. There’s also the ability to lock the screen on your location, and there are a few different ways of doing that.

Getting started

You will need to have already run through the remote image layer tutorial. Let’s get started by opening your HelloEarth project.

Xcode HelloEarth

If you haven’t got one here is a suitable ViewController file to start with (for Objective-C or Swift). This version is from the previous tutorial for a remote image layer.

Location privacy settings

In order for your app to get permission to access location services, you have to ask. In XCode, go into the settings for your project, and go to the Info tab. Under Custom iOS Target Properties, add an entry for “Privacy - Location When In Use…” The message you enter here will be displayed when the user’s prompted for location permission.

Requesting location permission

Tracking location

Implementing the MaplyLocationTrackerDelegate protocol

You can start tracking location with one simple command, but first you have to have an object implementing the MaplyLocationTrackerDelegate protocol. In our case, we’ll use the view controller class itself.

Change the class declaration to implement the protocol:

  • @interface ViewController : UIViewController <MaplyLocationTrackerDelegate>
  • class ViewController: UIViewController, MaplyLocationTrackerDelegate

Then, implement the location event callbacks:

  • - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
    }
    - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
    }
  •     func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        }
        func locationManager(_ manager: CLLocationManager, didChange status: CLAuthorizationStatus) {
        }

For now we’ll leave these empty, but they allow your app to respond to location events further up the line.

Start location tracking

Now, call the method startLocationTrackingWithDelegate:useHeading:useCourse:simulate:

  •     [theViewC startLocationTrackingWithDelegate:self useHeading:true useCourse:true simulate:false];
  •     theViewC!.startLocationTracking(with: self, useHeading: true, useCourse: true, simulate: false)

If you now run your app, you will see your current location marked on the map or globe. If heading or course are available, they will be indicated by an arrow on the marker.

Start tracking location

The first argument is the delegate, which in our case is the view controller class. The useHeading argument is true if heading should be used when available. The useCourse argument is true if course, when available, should be used as a fallback if heading is unavailable. Leave the last argument false for now.

Locking the map or globe on your location

Now, let’s keep the screen locked on the current location:

  •     [theViewC changeLocationTrackingLockType:MaplyLocationLockNorthUp];
  •     theViewC!.changeLocationTrackingLockType(MaplyLocationLockNorthUp)

In this example, as you travel the map will stay centered on your position.

Locking on

Lock modes

In the previous example your position stayed at the center of the screen, with the map or globe oriented North-up.

There are actually several lock modes available:

Lock mode Description
MaplyLocationLockNone Default behavior; screen doesn’t move with travel
MaplyLocationLockNorthUp Screen stays centered on user’s position, oriented North-up
MaplyLocationLockHeadingUp Screen stays centered on user’s position, oriented heading-up
MaplyLocationLockHeadingUpOffset User’s position is fixed to a point above or below the view’s center by an offset amount, oriented heading-up

Forward track and its offset

To use the MaplyLocationLockHeadingUpOffset locking mode, call the changeLocationTrackingLockType:forwardTrackOffset: method.

  •     [theViewC changeLocationTrackingLockType:MaplyLocationLockHeadingUpOffset forwardTrackOffset:150];
  •     theViewC!.changeLocationTrackingLockType(MaplyLocationLockHeadingUpOffset, forwardTrackOffset: 150)

The offset amount is the number of pixels below or above the center at which to fix the user’s position. A positive value is below.

Heading up offset mode

Simulating locations with headings

You can also simulate locations with headings. (The Apple development tools allow simulating position, but not heading).

In our example, declare a longitude variable amoung the class variables.

  •     float longitude;
  •     var longitude:Float?

Initialize it in viewDidLoad, before the startLocationTracking… method call.

  •     longitude = -120.0;
  •     longitude = -120.0

Then implement the MaplyLocationTrackerDelegate protocol’s getSimulationPoint method:

  • - (MaplyLocationTrackerSimulationPoint) getSimulationPoint {
        longitude += 0.001;
        MaplyLocationTrackerSimulationPoint simPoint;
        simPoint.latDeg = 49.0;
        simPoint.lonDeg = longitude;
        simPoint.headingDeg = 90.0;
        return simPoint;
    }
  •     func getSimulationPoint() -> MaplyLocationTrackerSimulationPoint {
            longitude = longitude! + 0.001
            return MaplyLocationTrackerSimulationPoint(lonDeg: longitude!, latDeg: 49.0, headingDeg: 90.0)
        }

What this will do is simulate a track that starts at 120W, 49N and moves eastward over time. (Every time the location tracker calls your getSimulationPoint method, the longitude is moved slightly eastward.)

Now change your startLocationTracking… method call so that simulate is set to true:

  •     [theViewC startLocationTrackingWithDelegate:self useHeading:true useCourse:true simulate:true];
  •     theViewC!.startLocationTracking(with: self, useHeading: true, useCourse: true, simulate: true)

The result in this example is a track moving eastward over the Canada-U.S. border.

Simulating an eastward track

Stop tracking location

Finally, to stop tracking location, simply call the stopLocationTracking method:

  •     [theViewC stopLocationTracking];
  •     theViewC!.stopLocationTracking()