Custom Location Source
Customize the location data source for NavigationMapView
and Navigation
. Obtain location data from user tap actions on the map.
This example shows how to customize your location data source for NavigationMapView
and Navigation
-
Custom your location data source for
NavigationMapView
, the location data value is from the user tap action on the map -
Custom your location data source for
Navigation

For all code examples, refer to Navigation Code Examples
CustomLocationSourceViewController view source
1import UIKit
2import NbmapNavigation
3import NbmapCoreNavigation
4import NbmapDirections
5import Nbmap
6
7class CustomLocationSourceViewController: UIViewController, NGLMapViewDelegate {
8
9 var navigationMapView: NavigationMapView? {
10 didSet {
11 oldValue?.removeFromSuperview()
12 if let navigationMapView = navigationMapView {
13 view.insertSubview(navigationMapView, at: 0)
14 }
15 }
16 }
17
18 var routes : [Route]? {
19 didSet {
20 guard routes != nil else{
21 startButton.isEnabled = false
22 return
23 }
24 startButton.isEnabled = true
25 }
26 }
27
28 var currentRouteIndex = 0
29
30 var startButton = UIButton()
31
32 override func viewDidLoad() {
33 super.viewDidLoad()
34
35 navigationMapView = NavigationMapView(frame: view.bounds)
36
37 navigationMapView?.locationManager = CustomMapLocationManager()
38
39 navigationMapView?.userTrackingMode = .followWithHeading
40
41 let singleTap = UILongPressGestureRecognizer(target: self, action: #selector(didLongPress(tap:)))
42 navigationMapView?.gestureRecognizers?.filter({ $0 is UILongPressGestureRecognizer }).forEach(singleTap.require(toFail:))
43 navigationMapView?.addGestureRecognizer(singleTap)
44
45 setupStartButton()
46
47 self.view.setNeedsLayout()
48
49 }
50
51 func setupStartButton() {
52 startButton.setTitle("Start", for: .normal)
53 startButton.layer.cornerRadius = 5
54 startButton.contentEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
55 startButton.backgroundColor = .blue
56
57 startButton.addTarget(self, action: #selector(tappedButton), for: .touchUpInside)
58 view.addSubview(startButton)
59 startButton.translatesAutoresizingMaskIntoConstraints = false
60 startButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -50).isActive = true
61 startButton.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor).isActive = true
62 startButton.titleLabel?.font = UIFont.systemFont(ofSize: 25)
63 }
64
65 @objc func tappedButton(sender: UIButton) {
66 guard let routes = self.routes else {
67 return
68 }
69 let navigationService = NBNavigationService(routes: routes, routeIndex: currentRouteIndex,locationSource: CustomNavigationLocationManager())
70 let navigationOptions = NavigationOptions(navigationService: navigationService)
71
72 let navigationViewController = NavigationViewController(for: routes,navigationOptions: navigationOptions)
73 navigationViewController.modalPresentationStyle = .fullScreen
74
75 present(navigationViewController, animated: true, completion: nil)
76 }
77
78 @objc func didLongPress(tap: UILongPressGestureRecognizer) {
79 guard let navigationMapView = navigationMapView, tap.state == .began else {
80 return
81 }
82 let coordinates = navigationMapView.convert(tap.location(in: navigationMapView), toCoordinateFrom: navigationMapView)
83 // Note: The destination name can be modified. The value is used in the top banner when arriving at a destination.
84 let destination = Waypoint(coordinate: coordinates, name: "\(coordinates.latitude),\(coordinates.longitude)")
85 addNewDestinationcon(coordinates: coordinates)
86
87 guard let currentLocation = navigationMapView.userLocation?.coordinate else { return}
88 let currentWayPoint = Waypoint.init(coordinate: currentLocation, name: "My Location")
89
90 requestRoutes(origin: currentWayPoint, destination: destination)
91 }
92
93
94 func addNewDestinationcon(coordinates: CLLocationCoordinate2D){
95 guard let mapView = navigationMapView else {
96 return
97 }
98
99 if let annotation = mapView.annotations?.last {
100 mapView.removeAnnotation(annotation)
101 }
102
103 let annotation = NGLPointAnnotation()
104 annotation.coordinate = coordinates
105 mapView.addAnnotation(annotation)
106 }
107
108 func requestRoutes(origin: Waypoint, destination: Waypoint){
109
110 let options = NavigationRouteOptions(origin: origin, destination: destination)
111
112 Directions.shared.calculate(options) { [weak self] routes, error in
113 guard let weakSelf = self else {
114 return
115 }
116 guard error == nil else {
117 print(error!)
118 return
119 }
120
121 guard let routes = routes else { return }
122
123
124 // Process or display routes information.For example,display the routes,waypoints and duration symbol on the map
125 weakSelf.navigationMapView?.showRoutes(routes)
126 weakSelf.navigationMapView?.showRouteDurationSymbol(routes)
127
128 guard let current = routes.first else { return }
129 weakSelf.navigationMapView?.showWaypoints(current)
130 weakSelf.routes = routes
131 }
132 }
133}
134
135
136CustomMapViewLocationManager View source
137import Nbmap
138import CoreLocation
139class CustomMapViewLocationManager: NSObject,NGLLocationManager {
140
141 var delegate: NGLLocationManagerDelegate? {
142 didSet {
143 locationManager.delegate = self
144 }
145 }
146
147 // Replace with your own location manager
148 private let locationManager = CLLocationManager()
149
150 var headingOrientation: CLDeviceOrientation {
151 get {
152 return locationManager.headingOrientation
153 }
154 set {
155 locationManager.headingOrientation = newValue
156 }
157 }
158
159 var desiredAccuracy: CLLocationAccuracy {
160 get {
161 return locationManager.desiredAccuracy
162 }
163 set {
164 locationManager.desiredAccuracy = newValue
165 }
166 }
167
168 var authorizationStatus: CLAuthorizationStatus {
169 if #available(iOS 14.0, *) {
170 return locationManager.authorizationStatus
171 } else {
172 return CLLocationManager.authorizationStatus()
173 }
174 }
175
176 var activityType: CLActivityType {
177 get {
178 return locationManager.activityType
179 }
180 set {
181 locationManager.activityType = newValue
182 }
183 }
184
185 @available(iOS 14.0, *)
186 var accuracyAuthorization: CLAccuracyAuthorization {
187 return locationManager.accuracyAuthorization
188 }
189
190 @available(iOS 14.0, *)
191 func requestTemporaryFullAccuracyAuthorization(withPurposeKey purposeKey: String) {
192 locationManager.requestTemporaryFullAccuracyAuthorization(withPurposeKey: purposeKey)
193 }
194
195 func dismissHeadingCalibrationDisplay() {
196 locationManager.dismissHeadingCalibrationDisplay()
197 }
198
199 func requestAlwaysAuthorization() {
200 locationManager.requestAlwaysAuthorization()
201 }
202
203 func requestWhenInUseAuthorization() {
204 locationManager.requestWhenInUseAuthorization()
205 }
206
207 func startUpdatingHeading() {
208 locationManager.startUpdatingHeading()
209 }
210
211 func startUpdatingLocation() {
212 locationManager.startUpdatingLocation()
213 }
214
215 func stopUpdatingHeading() {
216 locationManager.stopUpdatingHeading()
217 }
218
219 func stopUpdatingLocation() {
220 locationManager.stopUpdatingLocation()
221 }
222
223 deinit {
224 locationManager.stopUpdatingLocation()
225 locationManager.stopUpdatingHeading()
226 locationManager.delegate = nil
227 delegate = nil
228 }
229
230}
231// MARK: - CLLocationManagerDelegate , Please replace with your location data source delegate
232extension CustomMapLocationManager : CLLocationManagerDelegate {
233
234 func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
235 delegate?.locationManager(self, didUpdate: locations)
236 }
237
238 func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
239 delegate?.locationManager(self, didUpdate: newHeading)
240 }
241
242 func locationManagerShouldDisplayHeadingCalibration(_ manager: CLLocationManager) -> Bool {
243 return delegate?.locationManagerShouldDisplayHeadingCalibration(self) ?? false
244 }
245
246 func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
247 delegate?.locationManager(self, didFailWithError: error)
248 }
249
250 @available(iOS 14.0, *)
251 func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
252 delegate?.locationManagerDidChangeAuthorization(self)
253 }
254}
255
256
257CustomNavigationLocationManager view source
258import NbmapCoreNavigation
259import CoreLocation
260class CustomNavigationLocationManager : NavigationLocationManager {
261
262 override var delegate: CLLocationManagerDelegate? {
263 didSet {
264 locationManager.delegate = self
265 }
266 }
267
268 // Replace with your own location manager
269 private let locationManager = CLLocationManager()
270
271 override var headingOrientation: CLDeviceOrientation {
272 get {
273 return locationManager.headingOrientation
274 }
275 set {
276 locationManager.headingOrientation = newValue
277 }
278 }
279
280 override var desiredAccuracy: CLLocationAccuracy {
281 get {
282 return locationManager.desiredAccuracy
283 }
284 set {
285 locationManager.desiredAccuracy = newValue
286 }
287 }
288
289 override var authorizationStatus: CLAuthorizationStatus {
290 if #available(iOS 14.0, *) {
291 return locationManager.authorizationStatus
292 } else {
293 return CLLocationManager.authorizationStatus()
294 }
295 }
296
297 override var activityType: CLActivityType {
298 get {
299 return locationManager.activityType
300 }
301 set {
302 locationManager.activityType = newValue
303 }
304 }
305
306 @available(iOS 14.0, *)
307 override var accuracyAuthorization: CLAccuracyAuthorization {
308 return locationManager.accuracyAuthorization
309 }
310
311 @available(iOS 14.0, *)
312 override func requestTemporaryFullAccuracyAuthorization(withPurposeKey purposeKey: String) {
313 locationManager.requestTemporaryFullAccuracyAuthorization(withPurposeKey: purposeKey)
314 }
315
316 override func dismissHeadingCalibrationDisplay() {
317 locationManager.dismissHeadingCalibrationDisplay()
318 }
319
320 override func requestAlwaysAuthorization() {
321 locationManager.requestAlwaysAuthorization()
322 }
323
324 override func requestWhenInUseAuthorization() {
325 locationManager.requestWhenInUseAuthorization()
326 }
327
328 override func startUpdatingHeading() {
329 locationManager.startUpdatingHeading()
330 }
331
332 override func startUpdatingLocation() {
333 locationManager.startUpdatingLocation()
334 }
335
336 override func stopUpdatingHeading() {
337 locationManager.stopUpdatingHeading()
338 }
339
340 override func stopUpdatingLocation() {
341 locationManager.stopUpdatingLocation()
342 }
343
344 deinit {
345 locationManager.stopUpdatingLocation()
346 locationManager.stopUpdatingHeading()
347 locationManager.delegate = nil
348 delegate = nil
349 }
350
351}
352// MARK: - CLLocationManagerDelegate
353extension CustomNavigationLocationManager : CLLocationManagerDelegate {
354
355 func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
356 delegate?.locationManager!(self, didUpdateLocations: locations)
357 }
358
359 func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
360 delegate?.locationManager!(self, didUpdateHeading: newHeading)
361 }
362
363 func locationManagerShouldDisplayHeadingCalibration(_ manager: CLLocationManager) -> Bool {
364 return delegate?.locationManagerShouldDisplayHeadingCalibration!(self) ?? false
365 }
366
367 func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
368 delegate?.locationManager!(self, didFailWithError: error)
369 }
370
371 @available(iOS 14.0, *)
372 func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
373 delegate?.locationManagerDidChangeAuthorization!(self)
374 }
375}
376