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 smoothly works together with any proprietary positioning solution. In the future, a comprehensive HERE positioning solution is planned with more advanced features. 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 used.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app needs to access your current location to display it on the map while the app is used or when running in background.</string>

As a next step, 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.

Apparently, 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) {
    // ...
}

Then you can 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
    location.speedInMetersPerSecond = nativeLocation.speed
    location.horizontalAccuracyInMeters = nativeLocation.horizontalAccuracy
    location.verticalAccuracyInMeters = nativeLocation.verticalAccuracy

    return location
}

A practical example for this class can be seen in the Navigation example app, which is available for the Navigate Edition of the HERE SDK from here.

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

results matching ""

    No results matching ""