3
import NbmapCoreNavigation
7
class CustomLocationViewController: UIViewController ,NGLMapViewDelegate{
8
typealias ActionHandler = (UIAlertAction) -> Void
10
var navigationMapView: NavigationMapView! {
12
oldValue?.removeFromSuperview()
13
if let mapView = navigationMapView {
14
view.insertSubview(mapView, at: 0)
19
var routes : [Route]? {
21
guard routes != nil else{
22
startButton.isEnabled = false
25
startButton.isEnabled = true
29
private let startButton = UIButton()
31
override func viewDidLoad() {
34
self.navigationMapView = NavigationMapView(frame: view.bounds)
36
navigationMapView.userTrackingMode = .follow
37
let singleTap = UILongPressGestureRecognizer(target: self, action: #selector(didLongPress(tap:)))
38
navigationMapView?.gestureRecognizers?.filter({ $0 is UILongPressGestureRecognizer }).forEach(singleTap.require(toFail:))
39
navigationMapView?.addGestureRecognizer(singleTap)
40
navigationMapView?.delegate = self
42
let navigationViewportDataSource = NavigationViewportDataSource(navigationMapView)
43
navigationViewportDataSource.options.followingCameraOptions.zoomUpdatesAllowed = false
44
navigationViewportDataSource.followingMobileCamera = NavMapCameraOption()
45
navigationMapView.navigationCamera.viewportDataSource = navigationViewportDataSource
50
func setupStartButton() {
51
startButton.setTitle("Start", for: .normal)
52
startButton.layer.cornerRadius = 5
53
startButton.contentEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
54
startButton.backgroundColor = .blue
56
startButton.addTarget(self, action: #selector(performAction), for: .touchUpInside)
57
view.addSubview(startButton)
58
startButton.translatesAutoresizingMaskIntoConstraints = false
59
startButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -50).isActive = true
60
startButton.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor).isActive = true
61
startButton.titleLabel?.font = UIFont.systemFont(ofSize: 25)
64
@objc func didLongPress(tap: UILongPressGestureRecognizer) {
65
guard let mapView = navigationMapView, tap.state == .began else {
68
let coordinates = mapView.convert(tap.location(in: mapView), toCoordinateFrom: mapView)
70
let destination = Waypoint(coordinate: coordinates, name: "\(coordinates.latitude),\(coordinates.longitude)")
71
addNewDestinationcon(coordinates: coordinates)
73
guard let currentLocation = mapView.userLocation?.coordinate else { return}
74
let currentWayPoint = Waypoint.init(coordinate: currentLocation, name: "My Location")
76
requestRoutes(origin: currentWayPoint, destination: destination)
79
@objc func performAction(_ sender: Any) {
80
guard routes != nil else {
81
let alertController = UIAlertController(title: "Create route",
82
message: "Long tap on the map to create a route first.",
83
preferredStyle: .alert)
84
alertController.addAction(UIAlertAction(title: "OK", style: .default))
85
return present(alertController, animated: true)
88
let alertController = UIAlertController(title: "Choose UserLocationStyle",
89
message: "Select the user location style",
90
preferredStyle: .actionSheet)
92
let courseView: ActionHandler = { _ in self.setupCourseView() }
93
let defaultPuck2D: ActionHandler = { _ in self.setupDefaultPuck2D() }
94
let invisiblePuck: ActionHandler = { _ in self.setupInvisiblePuck() }
95
let puck2D: ActionHandler = { _ in self.setupCustomPuck2D() }
96
let cancel: ActionHandler = { _ in }
98
let actionPayloads: [(String, UIAlertAction.Style, ActionHandler?)] = [
99
("Invisible Puck", .default, invisiblePuck),
100
("Default Course View", .default, courseView),
101
("2D Default Puck", .default, defaultPuck2D),
102
("2D Custom Puck", .default, puck2D),
103
("Cancel", .cancel, cancel)
107
.map { payload in UIAlertAction(title: payload.0, style: payload.1, handler: payload.2) }
108
.forEach(alertController.addAction(_:))
110
if let popoverController = alertController.popoverPresentationController {
111
popoverController.sourceView = self.startButton
112
popoverController.sourceRect = self.startButton.bounds
115
present(alertController, animated: true, completion: nil)
118
func setupCourseView() {
119
presentNavigationViewController(.courseView())
122
func setupDefaultPuck2D() {
123
presentNavigationViewController(.puck2D)
126
func setupInvisiblePuck() {
127
presentNavigationViewController(.none)
130
func setupCustomPuck2D() {
131
let courseView = UserPuckCourseView(frame: CGRect(origin: .zero, size: 75.0))
132
courseView.puckView.image = UIImage(named: "airplane")
133
let userLocationStyle = UserLocationStyle.courseView(courseView)
134
presentNavigationViewController(userLocationStyle)
137
func presentNavigationViewController(_ userLocationStyle: UserLocationStyle? = nil) {
138
guard let routes = self.routes else {
141
let navigationService = NBNavigationService(routes: routes, routeIndex: 0)
142
let navigationOptions = NavigationOptions(navigationService: navigationService)
143
let navigationViewController = NavigationViewController(for: routes,navigationOptions: navigationOptions)
144
navigationViewController.modalPresentationStyle = .fullScreen
145
navigationViewController.navigationMapView?.userLocationStyle = userLocationStyle
146
present(navigationViewController, animated: true, completion: nil)
149
func addNewDestinationcon(coordinates: CLLocationCoordinate2D){
150
guard let mapView = navigationMapView else {
154
if let annotation = mapView.annotations?.last {
155
mapView.removeAnnotation(annotation)
158
let annotation = NGLPointAnnotation()
159
annotation.coordinate = coordinates
160
mapView.addAnnotation(annotation)
163
func requestRoutes(origin: Waypoint, destination: Waypoint){
165
let options = RouteOptions.init(origin: origin, destination: destination)
167
options.includesAlternativeRoutes = true
170
options.roadClassesToAvoid = []
173
options.distanceMeasurementSystem = MeasurementSystem.metric
175
Directions.shared.calculate(options) { [weak self] routes, error in
176
guard let weakSelf = self else {
179
guard error == nil else {
184
guard let routes = routes else { return }
188
weakSelf.navigationMapView?.showRoutes(routes)
189
weakSelf.navigationMapView?.showRouteDurationSymbol(routes)
191
guard let current = routes.first else { return }
192
weakSelf.navigationMapView?.showWaypoints(current)
193
weakSelf.routes = routes