Find Your Location

When building location-aware applications, one of the most common tasks is to show the current location of the user on a map. For this, there are many different solutions available. One possible way is to use Apple's CoreLocation to get locations from the device's built-in GPS sensors.

The HERE SDK works smoothly with any proprietary or platform positioning solution. Note that a comprehensive HERE positioning solution is available as part of the Navigate Edition. A possible platform dependent implementation is shown below.

Before accessing the device's sensors, you need to ask the user for permission. Add the following permissions to your Info.plist file:

<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs to access your current location to display it on the map while the app is being used.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app needs to access your current location to display it on the map while the app is being used or when running in background.</string>

Next, get an instance of the CLLocationManager from the iOS platform and request location updates:

locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()

To receive events, our class needs to conform to the CLLocationManagerDelegate protocol:

func locationManager(_ manager: CLLocationManager,
                     didUpdateLocations locations: [CLLocation]) {
    guard let lastLocation = locations.last else {
        print("Warning: No last location found")
        return
    }

    delegate?.onLocationUpdated(location: lastLocation)
}

// ...

delegate is of type PlatformPositioningProviderDelegate. This is a protocol we have defined to enable another class to easily get notified.

This is just an example of how to integrate a CLLocationManager that provides access to the iOS location services. Feel free to adapt it to your own needs.

Below you can find the complete class:

import CoreLocation
import Foundation
import UIKit

public protocol PlatformPositioningProviderDelegate {
    func onLocationUpdated(location: CLLocation)
}

// A simple iOS based positioning implementation.
class PlatformPositioningProvider : NSObject,
                                    CLLocationManagerDelegate {

    var delegate: PlatformPositioningProviderDelegate?
    private let locationManager = CLLocationManager()

    func startLocating() {
         if locationManager.delegate == nil {
             locationManager.delegate = self
             locationManager.desiredAccuracy = kCLLocationAccuracyBest
             locationManager.requestAlwaysAuthorization()
         }
    }

    func stopLocating() {
        locationManager.stopUpdatingLocation()
    }

    // Conforms to the CLLocationManagerDelegate protocol.
    func locationManager(_ manager: CLLocationManager,
                         didChangeAuthorization status: CLAuthorizationStatus) {
        switch status {
            case .restricted, .denied, .notDetermined:
                print("Positioning denied by user.")
                break
            case .authorizedWhenInUse, .authorizedAlways:
                print("Positioning authorized by user.")
                locationManager.startUpdatingLocation()
                break
            default:
                break
        }
    }

    // Conforms to the CLLocationManagerDelegate protocol.
    func locationManager(_ manager: CLLocationManager,
                         didFailWithError error: Error) {
       if let error = error as? CLError, error.code == .denied {
          print("Positioning denied by user.")
          manager.stopUpdatingLocation()
       }
    }

    // Conforms to the CLLocationManagerDelegate protocol.
    func locationManager(_ manager: CLLocationManager,
                         didUpdateLocations locations: [CLLocation]) {
        guard let lastLocation = locations.last else {
            print("Warning: No last location found")
            return
        }

        delegate?.onLocationUpdated(location: lastLocation)
    }
}

To integrate this class in your own app, create a new instance and set the calling class as delegate:

platformPositioningProvider = PlatformPositioningProvider()
platformPositioningProvider.delegate = self

By setting the calling class as delegate, you need to conform to the PlatformPositioningProviderDelegate protocol and your class can start to receive CLLocation events:

func onLocationUpdated(location: CLLocation) {
    // ...
}

You can then start and stop locating by calling the following methods:

platformPositioningProvider.startLocating()

// ...

platformPositioningProvider.stopLocating();

Note that our class receives CLLocation events. Use the following method to convert them to the Location class used by the HERE SDK to cover the most common fields:

private func convertLocation(nativeLocation: CLLocation) -> Location {
    let geoCoordinates = GeoCoordinates(latitude: nativeLocation.coordinate.latitude,
                                        longitude: nativeLocation.coordinate.longitude,
                                        altitude: nativeLocation.altitude)
    var location = Location(coordinates: geoCoordinates,
                            timestamp: nativeLocation.timestamp)
    location.bearingInDegrees = nativeLocation.course < 0 ? nil : nativeLocation.course
    location.speedInMetersPerSecond = nativeLocation.speed < 0 ? nil : nativeLocation.speed
    location.horizontalAccuracyInMeters = nativeLocation.horizontalAccuracy < 0 ? nil : nativeLocation.horizontalAccuracy
    location.verticalAccuracyInMeters = nativeLocation.verticalAccuracy < 0 ? nil : nativeLocation.verticalAccuracy

    return location
}

For more information on the CLLocationManager and how to utilize other platform positioning features, please refer to the official iOS documentation.

Note

A more comprehensive tutorial to build an app with HERE Positioning and GPX tracking features can be found here.

results matching ""

    No results matching ""