Tutorials / How to make an iOS App with a Map
Last Updated: October 03, 2020

Introduction

The HERE SDK for iOS allows developers to add location services into iOS applications. You can add rich location features such as geocoding, places search and positioning to your iOS Applications.

What you will learn

By completing this tutorial, you’ll learn how to render a map on iOS App using HERE iOS SDK.

Pre-Reqs.

  • An account with here-tech.skawa.fun
  • HERE iOS SDK

What we are going to build

In this tutorial, we will build an iOS map application.

Final Output

The following is the final output of the iOS app that we’re going to build:

HERE iOS SDK Features

  • Mapping
  • Search
  • Directions
  • Turn-by-Turn Navigation
  • HERE Positioning
  • Live Sense

You can find more information about the all the iOS SDK features from this link.

Acquiring HERE Credentials

To acquire the HERE credentials, follow the steps below:

  • Sign up / Login to here-tech.skawa.fun
  • Select the project
  • Scroll to the HERE SDK for iOS section
  • Then, click on Generate App ID and App Code button to generate credentials to access the iOS SDK
  • Finally, download the HERE SDK by click on the download link.

Create an iOS project using XCode

Before you get started, make sure you already downloaded HERE_iOS_SDK_Premium_xx_xx_xx.tar.gz to your desired location in your system.

Fire up the Xcode. From the Xcode menu select File > New > Project.

In the next screen select iOS > Application > Single View Application and click on Next button down below.

Now, provide the application name(such as MyHereMap) and an organization identifier(like edu.self.HelloMapHere).

Note: The buddle identifier should be the same as you’ve registered on here-tech.skawa.fun

Choose Swift under language, then click Next.

Navigate to the directory where you want to store the project in your system and then select Create.

In the next step add the iOS SDK to your project.

Add HERE SDK to your iOS project

In order to add the SDK to your project, extract the downloaded HERE_iOS_SDK_Premium_xx_xx_xx.tar.gz to your desired location in your system.

From the extracted files select NMAKit.framework file and drag and drop into the Frameworks, Libraries and Embedded Content section under the App > Target > General.

Also, ensure that NMAKit.framework file appears in “Embedded Binaries” and the “Linked Frameworks and Libraries” section.

Run the application. Form the Xcode menu bar, select Product > Run. Ensure that the project runs in the iOS Simulator without errors. In case if you run into error like below:

If you see an error similar to this, it is because you need to copy the framework into your project by dragging it into the “Project Files” area and then make sure that “Embed & Sign” was selected from the “General” screen above.

SDK for iOS is now ready for use in your Xcode project. Now that you have your project configured to work with HERE SDK, extending the sample application to render a map.

Create the Map View

In this section we will utilize NMAMapView and NMAGeoCoordinates classes to render a Map.

Create an NMAMapView.

Select Main.storyboard in the navigator, then click on the + button the top right corner to open the object library. Drag and drop a view object from the Object Library onto the View Controller. Resize the View so it takes up the entire viewable area in case needed.

Change the UIView class to the NMAMapView class as shown

Create an outlet for NMAmapView in ViewController

Select Main.Storyboard in the navigator. Press Option and click on the ViewController.swift to open the Assistant Editor. It should show ViewController.swift file.

Add the following import statement to the top of this file:

import NMAKit 

Hold the Control Key on the Keyboard and click to drag from the Map View to the interface block in ViewController.swift. You should see a blue line and tooltip which “Insert Outlet or Outlet Connection”. Release the mouse button and dialog appears allowing you to create an outlet.

Name the outlet mapView, keep the other default options and then select Connect.

Now an outlet to NMAMapView is set. Now add the following code to render a Map in the viewDidLoad method after super.viewDidLoad() statement:

       //create geo coordinate
             let geoCoordCenter = NMAGeoCoordinates(latitude: 49.260327, longitude: -123.115025)
             //set map view with geo center
        self.mapView.set(geoCenter: geoCoordCenter, animation: .linear)
             //set zoom level
             self.mapView.zoomLevel = 13.2;

Add your HERE application credentials.

Open AppDelegate.swift and import NMAKit by adding the following import statement to the top of the file.

import NMAKit

Add the following in didFinishLaunchingWithOptions function replacing YOUR_APP_ID, YOUR_APP_CODE and YOUR_LICENSE_KEY with the credentials that you received from your http://here-tech.skawa.fun.

NMAApplicationContext.setAppId("YOUR_APP_ID",
    appCode: "YOUR_APP_CODE",
    licenseKey: "YOUR_LICENSE_KEY")

Finally, your AppDelegate.swift should look as shown:


import UIKit
import NMAKit

let credentials = (
    appId: "here-appId",
    appCode: "here-appCode",
    licenseKey: "here-licenseKey"
)
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        NMAApplicationContext.setAppId(credentials.appId, appCode: credentials.appCode, licenseKey: credentials.licenseKey)
        return true
    }
    // MARK: UISceneSession Lifecycle

    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        // Called when a new scene session is being created.
        // Use this method to select a configuration to create the new scene with.
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }

    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
        // Called when the user discards a scene session.
        // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
        // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
    }

}

Build and run application. If the build is successful, you now have an application that displays a map similar to the following screenshot.

Get Current User Location

To get the current user location you need to do the following:

  • Setup the Location Manager
  • Get the user permissions
  • Display a marker on the current location.

Firstly, import the required libs as shown below:

 import CoreLocation 
 import MapKit

The following is the function to setup the Location Manager. You need to copy and paste it inside the ViewController after the ViewDidLoad function.


    func setupLocationManager(){
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
    }
    

Get user permission

To the access the user current location you need to ask the permission to access the location.

The following code will help you get the same. You need to copy and paste the following code after the setupLocationManager function.

  func checkLocationServices(){
        if CLLocationManager.locationServicesEnabled(){
            setupLocationManager()
            checkLocationAuthorization()
          
        }else{
            // show alert letting the user know that they have to turn the location on
        }
    }
    
    func checkLocationAuthorization(){
        switch CLLocationManager.authorizationStatus() {
        case .denied:
            break
        case .notDetermined:
            locationManager.requestWhenInUseAuthorization()
            break
        case .restricted:
            break
        case .authorizedAlways, .authorizedWhenInUse:
                   addMarkerToUserLocation()
            break
  
        }
    }

Display a marker on the current location

In this step you need to create a function to create a maker and add to the current location of the user.

You need to download the Marker Icons from this link and add it inside the project folder as shown.

Copy and paste the below code after the checkLocationAuthorization method in the ViewController.swift file.

    func addMarkerToUserLocation(){
          
           if let location = locationManager.location?.coordinate {
            
            
            let point = NMAGeoCoordinates(latitude:location.latitude,longitude:location.longitude)
            self.mapView.set(geoCenter: point, zoomLevel: 13, animation: .linear)
            
             let mapMarker = NMAMapMarker(geoCoordinates: point, image: UIImage(named: "marker_icon.png")!)
            
            self.mapView.add(mapObject: mapMarker)
            
            self.mapView.set(geoCenter: point, zoomLevel: 13, animation: .linear)
                
            }
        }
    

Finally, add the following code after ViewController class. This will attach location delegate to the ViewController.


extension ViewController:CLLocationManagerDelegate {
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        // we will back
    }
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        checkLocationAuthorization()
    }
}

Finally, the ViewController.swift file should look as shown:


import UIKit
import NMAKit

import CoreLocation
import MapKit

class ViewController: UIViewController {

    @IBOutlet weak var mapView: NMAMapView!
    
    let locationManager = CLLocationManager()
    
    override func viewDidLoad() {
        super.viewDidLoad()

        //create geo coordinate
        let geoCoordCenter = NMAGeoCoordinates(latitude: 49.260327, longitude: -123.115025)
        
        DispatchQueue.main.async {
            //set map view with geo center
            self.mapView.set(geoCenter: geoCoordCenter, animation: .linear)
            //set zoom level
            self.mapView.zoomLevel = 13.2;
        }
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        checkLocationServices()
    }
    
    func setupLocationManager(){
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
    }
    
    func checkLocationServices(){
          if CLLocationManager.locationServicesEnabled(){
              setupLocationManager()
              checkLocationAuthorization()
            
          }else{
              // show alert letting the user know that they have to turn the location on
          }
      }
      
      func checkLocationAuthorization(){
          switch CLLocationManager.authorizationStatus() {
          case .denied:
              break
          case .notDetermined:
              locationManager.requestWhenInUseAuthorization()
              break
          case .restricted:
              break
          case .authorizedAlways, .authorizedWhenInUse:
            locationManager.startUpdatingLocation()
                     addMarkerToUserLocation()
              break
    
          @unknown default:
            fatalError()
        }
      }
    
    func addMarkerToUserLocation(){
          
           if let location = locationManager.location?.coordinate {
            
            
            let point = NMAGeoCoordinates(latitude:location.latitude,longitude:location.longitude)
            self.mapView.set(geoCenter: point, zoomLevel: 13, animation: .linear)
            
             let mapMarker = NMAMapMarker(geoCoordinates: point, image: UIImage(named: "marker_icon.png")!)
            
            self.mapView.add(mapObject: mapMarker)
            
            self.mapView.set(geoCenter: point, zoomLevel: 13, animation: .linear)
                
            }
        }
    



}

extension ViewController:CLLocationManagerDelegate {
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        
        if let position = locations.first {
            let point = NMAGeoCoordinates(latitude:position.coordinate.latitude,longitude:position.coordinate.longitude)
            self.mapView.set(geoCenter: point, zoomLevel: 13, animation: .linear)
            
            let mapMarker = NMAMapMarker(geoCoordinates: point)
            
            self.mapView.add(mapObject: mapMarker)
            
            self.mapView.set(geoCenter: point, zoomLevel: 13, animation: .linear)
        }
        
        
    }
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        checkLocationAuthorization()
    }
}

There is one last step you need to do, add the privacy location property to your info.plist

Privacy - Location When In Use Usage Description : This is used to show the current user location

Run the project will and you should screen similar to below:

Conclusion

By following the above tutorial, you should now be familiar with:

  • Importing the HERE-SDK
  • Implementing the HERE Map using HERE SDK for iOS
  • Displaying a Marker in the current location of the user

Next Steps

Checkout our related content: