Display User Location

This section of the iOS Maps SDK provides developers with the necessary tools and guidelines to incorporate user location functionality into their applications. This functionality allows users to see their current location on the map, providing a more personalized and interactive experience.

Permissions

This section explains the importance of obtaining the necessary location permissions from the user. It provides information on how to request location permissions and handle user responses. Ensuring that the appropriate permissions are obtained is crucial for accessing and displaying the user's location accurately and securely.

Add the following to the info.plist

1<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
2<string>YOUR_DESCRIPTION</string>
3<key>NSLocationAlwaysUsageDescription</key>
4<string>YOUR_DESCRIPTION</string>

Replace YOUR_DESCRIPTION with a short description of the location information your application uses. Permission requests are automatically triggered by the Maps SDK when obtaining location information

Location provider/Component

You can use the following code to display the current location on the map. mapView.showsUserLocation = true

You can also use your own location component. Here is an example of MapView using a custom Location component.

  1. Create custom MapLocationManager
1import Nbmap
2import CoreLocation
3class CustomMapLocationManager: NSObject,NGLLocationManager {
4    
5    var delegate: NGLLocationManagerDelegate? {
6        didSet {
7            locationManager.delegate = self
8        }
9    }
10    
11    // Replay with your own location manager
12    private let locationManager = CLLocationManager()
13    
14    var headingOrientation: CLDeviceOrientation {
15        get {
16            return locationManager.headingOrientation
17        }
18        set {
19            locationManager.headingOrientation = newValue
20        }
21    }
22    
23    var desiredAccuracy: CLLocationAccuracy {
24        get {
25            return locationManager.desiredAccuracy
26        }
27        set {
28            locationManager.desiredAccuracy = newValue
29        }
30    }
31    
32    var authorizationStatus: CLAuthorizationStatus {
33        if #available(iOS 14.0, *) {
34            return locationManager.authorizationStatus
35        } else {
36            return CLLocationManager.authorizationStatus()
37        }
38    }
39    
40    var activityType: CLActivityType {
41        get {
42            return locationManager.activityType
43        }
44        set {
45            locationManager.activityType = newValue
46        }
47    }
48    
49    @available(iOS 14.0, *)
50    var accuracyAuthorization: CLAccuracyAuthorization {
51        return locationManager.accuracyAuthorization
52    }
53    
54    @available(iOS 14.0, *)
55    func requestTemporaryFullAccuracyAuthorization(withPurposeKey purposeKey: String) {
56        locationManager.requestTemporaryFullAccuracyAuthorization(withPurposeKey: purposeKey)
57    }
58    
59    func dismissHeadingCalibrationDisplay() {
60        locationManager.dismissHeadingCalibrationDisplay()
61    }
62    
63    func requestAlwaysAuthorization() {
64        locationManager.requestAlwaysAuthorization()
65    }
66    
67    func requestWhenInUseAuthorization() {
68        locationManager.requestWhenInUseAuthorization()
69    }
70    
71    func startUpdatingHeading() {
72        locationManager.startUpdatingHeading()
73    }
74    
75    func startUpdatingLocation() {
76        locationManager.startUpdatingLocation()
77    }
78    
79    func stopUpdatingHeading() {
80        locationManager.stopUpdatingHeading()
81    }
82    
83    func stopUpdatingLocation() {
84        locationManager.stopUpdatingLocation()
85    }
86    
87    deinit {
88        locationManager.stopUpdatingLocation()
89        locationManager.stopUpdatingHeading()
90        locationManager.delegate = nil
91        delegate = nil
92    }
93    
94}
95// MARK: - CLLocationManagerDelegate
96extension CustomMapLocationManager : CLLocationManagerDelegate {
97  
98    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
99        delegate?.locationManager(self, didUpdate: locations)
100    }
101    
102    func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
103        delegate?.locationManager(self, didUpdate: newHeading)
104    }
105    
106    func locationManagerShouldDisplayHeadingCalibration(_ manager: CLLocationManager) -> Bool {
107        return delegate?.locationManagerShouldDisplayHeadingCalibration(self) ?? false
108    }
109    
110    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
111        delegate?.locationManager(self, didFailWithError: error)
112    }
113    
114
115    @available(iOS 14.0, *)
116    func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
117        delegate?.locationManagerDidChangeAuthorization(self)
118    }
119}
  1. Use custom location manager
1import Foundation
2import UIKit
3import Nbmap
4class CustomLocationSourceViewController: UIViewController {
5    var nbMapView: NGLMapView! {
6        didSet {
7            oldValue?.removeFromSuperview()
8            if let mapView = nbMapView {
9                view.insertSubview(mapView, at: 0)
10            }
11        }
12    }
13    override func viewDidLoad() {
14        super.viewDidLoad()
15        nbMapView = NGLMapView(frame:self.view.bounds)
16        nbMapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
17        
18        /**
19         Custom the location source , The locationManager that this map view uses to start and stop the delivery of
20         location-related updates.
21         To receive the current user location, implement the
22         `-[NGLMapViewDelegate mapView:didUpdateUserLocation:]` and
23         `-[NGLMapViewDelegate mapView:didFailToLocateUserWithError:]` methods.
24         If setting this property to `nil` or if no custom manager is provided this
25         property is set to the default location manager.
26         `NGLMapView` uses a default location manager. If you want to substitute your
27         own location manager, you should do so by setting this property before setting
28         `showsUserLocation` to `YES`. To restore the default location manager,
29         set this property to `nil`.
30         */
31        nbMapView.locationManager = CustomMapLocationManager()
32        nbMapView.showsUserLocation = true
33        nbMapView.userTrackingMode = .follow
34    }
35}

Location Puck

The location puck refers to the graphical representation of the user's current location on the map. This subsection discusses how to customize and style the location puck to match the app's design and provide a clear visual indication of the user's position on the map. Developers can learn how to adjust the size, color, and shape of the location puck to meet their application's requirements.

Code example: show user location on the map and customise puck view

1import UIKit
2import Nbmap
3class CustomPuckViewController: UIViewController {
4    var nbMapView: NGLMapView! {
5        didSet {
6            oldValue?.removeFromSuperview()
7            if let mapView = nbMapView {
8                view.insertSubview(mapView, at: 0)
9            }
10        }
11    }
12    override func viewDidLoad() {
13        super.viewDidLoad()
14        nbMapView = NGLMapView(frame:self.view.bounds)
15        nbMapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
16        nbMapView.delegate = self
17        nbMapView.userTrackingMode = .follow
18    }
19}
20// MARK: - NGLMapViewDelegate
21extension CustomPuckViewController: NGLMapViewDelegate {
22 
23    /**
24     Asks the user styling options for each default user location annotation view.
25     
26     This method is called many times during gesturing, so you should avoid performing
27     complex or performance-intensive tasks in your implementation.
28     
29     @param mapView The map view that is tracking the user's location.
30     */
31    func mapView(styleForDefaultUserLocationAnnotationView mapView: NGLMapView) -> NGLUserLocationAnnotationViewStyle {
32        let locationStyle =  NGLUserLocationAnnotationViewStyle()
33        /**
34         The fill color for the puck view.
35         */
36        locationStyle.puckFillColor = UIColor.blue
37        /**
38         The shadow color for the puck view.
39         */
40        locationStyle.puckShadowColor = UIColor.red
41        /**
42         The shadow opacity for the puck view.
43         Set any value between 0.0 and 1.0.
44         The default value of this property is equal to `0.25`
45         */
46        locationStyle.puckShadowOpacity = 0.25
47        /**
48         The fill color for the arrow puck.
49         */
50        locationStyle.puckArrowFillColor = UIColor.black
51        /**
52         The fill color for the puck view.
53         */
54        locationStyle.haloFillColor = UIColor.white
55       
56        if #available(iOS 14, *) {
57            /**
58             The halo fill color for the approximate view.
59             */
60            locationStyle.approximateHaloFillColor = UIColor.white
61            /**
62             The halo border color for the approximate view.
63             */
64            locationStyle.approximateHaloBorderColor = UIColor.white
65            /**
66             The halo border width for the approximate view.
67             The default value of this property is equal to `2.0`
68             */
69            locationStyle.approximateHaloBorderWidth = 2.0
70            /**
71             The halo opacity for the approximate view.
72             Set any value between 0.0 and 1.0
73             The default value of this property is equal to `0.15`
74             */
75            locationStyle.approximateHaloOpacity = 0.15
76        }
77      
78        return locationStyle
79    }
80    
81    /**
82     Returns a view object to mark the given point annotation object on the map.
83     Implement this method to mark a point annotation with a view object. If you
84     want to mark a particular point annotation with a static image instead, omit
85     this method or have it return `nil` for that annotation, then implement
86     `-mapView:imageForAnnotation:` instead.
87     Annotation views are compatible with UIKit, Core Animation, and other Cocoa
88     Touch frameworks. On the other hand, static annotation images use less memory
89     and draw more quickly than annotation views.
90     The user location annotation view can also be customized via this method. When
91     `annotation` is an instance of `NGLUserLocation` (or equal to the map view's
92     `userLocation` property), return an instance of `NGLUserLocationAnnotationView`
93     (or a subclass thereof).
94     @param mapView The map view that requested the annotation view.
95     @param annotation The object representing the annotation that is about to be
96        displayed.
97     @return The view object to display for the given annotation or `nil` if you
98        want to display an annotation image instead.
99     */
100    func mapView(_ mapView: NGLMapView, viewFor annotation: NGLAnnotation) -> NGLAnnotationView?  {
101        let annotationView = CustomUserLocationAnnotationView(frame: CGRect.zero)
102        annotationView.frame = CGRect(x:0, y:0, width:annotationView.intrinsicContentSize.width, height:annotationView.intrinsicContentSize.height);
103        return annotationView
104    }
105  
106}

Location tracking mode

This subsection focuses on different location tracking modes available in the iOS Maps SDK. It explains the concept of location tracking modes, such as "follow," "follow with course," and "follow with heading." Developers can understand how each tracking mode works and choose the appropriate one based on their application's needs. These modes enable the map to dynamically adjust and center on the user's location as they move, providing a smooth and intuitive user experience.

The provided code example demonstrates how to show the user's location on a map and change the tracking mode using the iOS Maps SDK.

1import UIKit
2import Nbmap
3enum LocationType {
4    case HidePuckView
5    case UpdateToFollow
6    case UpdateToFollowWithHeading
7    case UpdateToFollowWithCourse
8    case GetUserLocation
9}
10class LocationStyleViewController: UIViewController {
11    var nbMapView: NGLMapView! {
12        didSet {
13            oldValue?.removeFromSuperview()
14            if let mapView = nbMapView {
15                view.insertSubview(mapView, at: 0)
16            }
17        }
18    }
19    
20    var button: UIButton!
21    
22    let typeList = [
23        LocationType.HidePuckView,
24        LocationType.UpdateToFollow,
25        LocationType.UpdateToFollowWithCourse,
26        LocationType.UpdateToFollowWithHeading,
27        LocationType.GetUserLocation
28    ]
29    
30    override func viewDidLoad() {
31        super.viewDidLoad()
32        nbMapView = NGLMapView(frame:self.view.bounds)
33        nbMapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
34        nbMapView.delegate = self
35        
36        button = UIButton(type: .system)
37        button.setTitle("Settings", for: .normal)
38        button.addTarget(self, action: #selector(showSetings), for: .touchUpInside)
39        button.frame = CGRect(x: 0, y: 0, width: 100, height: 40)
40        navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button)
41    }
42    
43    @objc func showSetings() {
44        let tableViewController = UITableViewController(style: .plain)
45        tableViewController.tableView.delegate = self
46        tableViewController.tableView.dataSource = self
47        tableViewController.title = "Locations Settings"
48        self.present(tableViewController, animated: true)
49    }
50    
51    func performeSettings(tyle: LocationType) {
52        switch tyle {
53        case LocationType.UpdateToFollow:
54            nbMapView.setUserTrackingMode(.follow,animated: true,completionHandler: nil)
55            break
56        case LocationType.UpdateToFollowWithCourse:
57            nbMapView.setUserTrackingMode(.followWithCourse,animated: true,completionHandler: nil)
58            break
59        case LocationType.UpdateToFollowWithHeading:
60            nbMapView.setUserTrackingMode(.followWithHeading,animated: true,completionHandler: nil)
61            break
62        case LocationType.HidePuckView:
63            nbMapView.setUserTrackingMode(.none,animated: true,completionHandler: nil)
64            break
65        case LocationType.GetUserLocation:
66            if let userLocation = nbMapView.userLocation {
67                let location = userLocation.location
68                let isUpdating = userLocation.isUpdating
69                let title = userLocation.title
70                let subtitle = userLocation.subtitle ?? ""
71                print("location:" + location!.description)
72                print("isUpdating:" + String(isUpdating))
73                print("title:" + title)
74                print("subtitle:" + subtitle)
75                if let heading = userLocation.heading {
76                    print(heading.description)
77                }
78            }
79            break
80        }
81       
82    }
83}
84extension LocationStyleViewController: NGLMapViewDelegate {
85    func mapView(_ mapView: NGLMapView, didFinishLoading style: NGLStyle){
86        
87        let camera = NGLMapCamera(lookingAtCenter: CLLocationCoordinate2DMake(12.94798778, 77.57375084),
88                                                                      acrossDistance:10000,
89                                                                               pitch:0,
90                                                                             heading:0)
91        nbMapView.fly(to: camera)
92    
93    }
94    
95    /**
96     Tells the user that the map view will begin tracking the user's location.
97     This method is called when the value of the `showsUserLocation` property
98     changes to `YES`.
99     @param mapView The map view that is tracking the user's location.
100     */
101    func mapViewWillStartLocatingUser(_ mapView: NGLMapView) {
102       
103    }
104    
105    /**
106     Tells the user that the map view has stopped tracking the user's location.
107     This method is called when the value of the `showsUserLocation` property
108     changes to `NO`.
109     @param mapView The map view that is tracking the user's location.
110     */
111    func mapViewDidStopLocatingUser(_ mapView: NGLMapView) {
112       
113    }
114    
115    
116    /**
117     Asks the user styling options for each default user location annotation view.
118     
119     This method is called many times during gesturing, so you should avoid performing
120     complex or performance-intensive tasks in your implementation.
121     
122     @param mapView The map view that is tracking the user's location.
123     */
124    func mapView(styleForDefaultUserLocationAnnotationView mapView: NGLMapView) -> NGLUserLocationAnnotationViewStyle {
125        let locationStyle =  NGLUserLocationAnnotationViewStyle()
126        /**
127         The fill color for the puck view.
128         */
129        locationStyle.puckFillColor = UIColor.blue
130        /**
131         The shadow color for the puck view.
132         */
133        locationStyle.puckShadowColor = UIColor.red
134        /**
135         The shadow opacity for the puck view.
136         Set any value between 0.0 and 1.0.
137         The default value of this property is equal to `0.25`
138         */
139        locationStyle.puckShadowOpacity = 0.25
140        /**
141         The fill color for the arrow puck.
142         */
143        locationStyle.puckArrowFillColor = UIColor.black
144        /**
145         The fill color for the puck view.
146         */
147        locationStyle.haloFillColor = UIColor.white
148       
149        if #available(iOS 14, *) {
150            /**
151             The halo fill color for the approximate view.
152             */
153            locationStyle.approximateHaloFillColor = UIColor.white
154            /**
155             The halo border color for the approximate view.
156             */
157            locationStyle.approximateHaloBorderColor = UIColor.white
158            /**
159             The halo border width for the approximate view.
160             The default value of this property is equal to `2.0`
161             */
162            locationStyle.approximateHaloBorderWidth = 2.0
163            /**
164             The halo opacity for the approximate view.
165             Set any value between 0.0 and 1.0
166             The default value of this property is equal to `0.15`
167             */
168            locationStyle.approximateHaloOpacity = 0.15
169        }
170      
171        return locationStyle
172    }
173    
174    /**
175     Tells the user that the location of the user was updated.
176     While the `showsUserLocation` property is set to `YES`, this method is called
177     whenever a new location update is received by the map view. This method is also
178     called if the map view's user tracking mode is set to
179     `NGLUserTrackingModeFollowWithHeading` and the heading changes, or if it is set
180     to `NGLUserTrackingModeFollowWithCourse` and the course changes.
181     This method is not called if the application is currently running in the
182     background. If you want to receive location updates while running in the
183     background, you must use the Core Location framework.
184     private  @param mapView The map view that is tracking the user's location.
185     @param userLocation The location object represents the user's latest
186        location. This property may be `nil`.
187     */
188    func mapView(_ mapView: NGLMapView, didUpdate userLocation: NGLUserLocation?) {
189        
190    }
191  
192    /**
193     Tells the user that an attempt to locate the user's position failed.
194     @param mapView The map view that is tracking the user's location.
195     @param error An error object containing the reason why location tracking
196        failed.
197     */
198    func mapView(_ mapView: NGLMapView, didFailToLocateUserWithError error: Error)  {
199        
200    }
201    
202    
203    /**
204     Tells the user that the map view's user tracking mode has changed.
205     This method is called after the map view asynchronously changes to reflect the
206     new user tracking mode, for example by beginning to zoom or rotate.
207     private  @param mapView The map view changed its tracking mode.
208     @param mode The new tracking mode.
209     @param animated Whether the change caused an animated effect on the map.
210     */
211    func mapView(_ mapView: NGLMapView, didChange mode: NGLUserTrackingMode, animated: Bool )  {
212        
213    }
214  
215    /**
216     Returns a screen coordinate at which to position the user location annotation.
217     This coordinate is relative to the map view's origin after applying the map view's
218     content insets.
219     When unimplemented, the user location annotation is aligned within the center of
220     the map view with respect to the content insets.
221     This method will override any values set by `NGLMapView.userLocationVerticalAlignment`
222     or `-[NGLMapView setUserLocationVerticalAlignment:animated:]`.
223     @param mapView The map view that is tracking the user's location.
224     
225     Notes: We don't need to set the anchor point for now, so comment out this method first
226     */
227//    func mapViewUserLocationAnchorPoint(_ mapView: NGLMapView ) -> CGPoint  {
228//
229//    }
230    /**
231     Tells the user that the map's location updates accuracy authorization has changed.
232     
233     This method is called after the user changes location accuracy authorization when
234     requesting location permissions or in privacy settings.
235     
236     @param mapView The map view that changed its location accuracy authorization.
237     @param manager The location manager reporting the update.
238     
239     */
240    func mapView(_ apView: NGLMapView, didChangeLocationManagerAuthorization manager: NGLLocationManager)  {
241        
242    }
243    
244    /**
245     Returns a view object to mark the given point annotation object on the map.
246     Implement this method to mark a point annotation with a view object. If you
247     want to mark a particular point annotation with a static image instead, omit
248     this method or have it return `nil` for that annotation, then implement
249     `-mapView:imageForAnnotation:` instead.
250     Annotation views are compatible with UIKit, Core Animation, and other Cocoa
251     Touch frameworks. On the other hand, static annotation images use less memory
252     and draw more quickly than annotation views.
253     The user location annotation view can also be customized via this method. When
254     `annotation` is an instance of `NGLUserLocation` (or equal to the map view's
255     `userLocation` property), return an instance of `NGLUserLocationAnnotationView`
256     (or a subclass thereof).
257     @param mapView The map view that requested the annotation view.
258     @param annotation The object representing the annotation that is about to be
259        displayed.
260     @return The view object to display for the given annotation or `nil` if you
261        want to display an annotation image instead.
262     */
263    func mapView(_ mapView: NGLMapView, viewFor annotation: NGLAnnotation) -> NGLAnnotationView?  {
264        return nil
265    }
266  
267}
268extension LocationStyleViewController: UITableViewDelegate, UITableViewDataSource {
269    
270    func settingsTitlesForRaw(index: Int) -> String {
271        let type = typeList[index]
272        var title: String = ""
273        switch type {
274        case LocationType.HidePuckView :
275                title = "Hide puck view"
276            break
277        case LocationType.UpdateToFollowWithHeading:
278            title = "Update puck view to follow with heading"
279            break
280        case LocationType.UpdateToFollowWithCourse:
281            title = "Update puck view to follow with course"
282            break
283        case LocationType.UpdateToFollow:
284            title = "Update puck view to follow"
285            break
286        case LocationType.GetUserLocation:
287            title = "Get user location"
288            break
289        }
290        return title
291    }
292   
293     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
294         return typeList.count
295     }
296     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
297         let cell = UITableViewCell(style: .default, reuseIdentifier: nil)
298         cell.textLabel?.text = settingsTitlesForRaw(index: indexPath.row)
299         return cell
300     }
301     func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
302         tableView.isHidden = true
303         let type = typeList[indexPath.row]
304        dismissSettings(type: type)
305     }
306    
307    func dismissSettings(type: LocationType) {
308        dismiss(animated: true)
309        performeSettings(tyle: type)
310    }
311}

Let's break down the code:

Import Statements:

  1. The code begins with the import statements for the required frameworks, UIKit and Nbmap.

Enum Declaration:

  1. The LocationType enum defines different types of location settings, such as hiding the puck view, updating to follow the user's location, updating to follow with a heading, updating to follow with a course, and getting the user's location.

Class Declaration:

  1. The LocationStyleViewController class is a subclass of UIViewController and serves as the main view controller for the location functionality.

  2. It declares a property nbMapView of type NGLMapView to display the map view and handles its setup and removal.

  3. It also declares a property button of type UIButton to show a settings button on the navigation bar.

  4. The class includes an array typeList that stores the different LocationType options.

  5. The viewDidLoad() method initializes the nbMapView and sets its delegate. It also sets up the settings button on the navigation bar.

  6. The showSettings() method is called when the settings button is tapped. It presents a table view controller to display location settings options.

  7. The performSettings(type:) method is called when a location setting is selected. It performs the corresponding action based on the selected LocationType.

Extensions:

  1. The LocationStyleViewController extension implements the NGLMapViewDelegate protocol, providing necessary delegate methods for the map view.

  2. The mapView(_:didFinishLoading:) method is called when the map finishes loading. It sets the initial camera position.

  3. Other delegate methods, such as mapViewWillStartLocatingUser, mapViewDidStopLocatingUser, and mapView(_:didChange:animated:), are implemented but are currently empty. They can be used to handle various events related to user location tracking.

  4. The mapView(styleForDefaultUserLocationAnnotationView:) method customizes the appearance of the user location annotation view by setting properties such as puckFillColor, puckShadowColor, and haloFillColor.

  5. The mapView(_:didUpdate:) method is called when the user's location is updated. Currently, it is empty and can be used to perform actions based on the user's updated location.

  6. Other delegate methods, such as mapView(_:didFailToLocateUserWithError:) and mapView(_:didChangeLocationManagerAuthorization:), are implemented but are currently empty.

Additional Extensions:

  1. The LocationStyleViewController extension implements the UITableViewDelegate and UITableViewDataSource protocols to handle the settings table view.

  2. The methods in these extensions populate the table view with the available location settings options and handle selection.

  3. The dismissSettings(type:) method is called when a location setting is selected, and it dismisses the settings view controller and performs the corresponding action.

Overall, the code example provides a view controller that displays a map view, handles user location tracking, and allows the user to change the location tracking mode based on different settings.

Getting Started
Annotations
DIDN'T FIND WHAT YOU LOOKING FOR?