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

docs-image

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