Commit fc0ee1ad authored by Ariba Siddiqui's avatar Ariba Siddiqui
Browse files

Comments and otehr restrucuring

parent 1377bbc9
......@@ -2,8 +2,6 @@
// LocationFinder.swift
// MapKit Testing Search Functionality
//
// Created by Brian Porumb on 25.11.21.
//
import Foundation
import Combine
......@@ -11,7 +9,7 @@ import MapKit
class LocationService: NSObject, ObservableObject {
// Differnt search states
// Different search states
enum LocationStatus: Equatable {
case idle
case noResults
......@@ -37,11 +35,11 @@ class LocationService: NSObject, ObservableObject {
self.searchCompleter.delegate = self
// receive a stream from the queryFragment in the view
// debounce (wait) for 250miliseconds before pushing the event further
// debounce (wait) for 500 milliseconds before pushing the event further
// sink returns the updated string after waiting the specified amount of time
queryCancellable = $queryFragment
.receive(on: DispatchQueue.main)
.debounce(for: .milliseconds(250), scheduler: RunLoop.main, options: nil)
.debounce(for: .milliseconds(500), scheduler: RunLoop.main, options: nil)
.sink(receiveValue: { fragment in
// if fragment isn't empty then set the queryFrament to the current updated string
......
//
// ContentView.swift
// MapSearchView.swift
// MapKit Testing Search Functionality
//
// Created by Brian Porumb on 25.11.21.
//
import SwiftUI
......
//
// ViewController.swift
// Location Tutorial
//
// Created by Huang on 2021/11/25.
// MapKit Routing, Annotations and Location
//
import UIKit
......@@ -14,26 +12,31 @@ class ViewController: UIViewController {
@IBOutlet weak var mapView: MKMapView!
let locationManager = CLLocationManager()
var regionInMeters: Double = 10000 //scale of the map
// ### code for directions start ###
var directionsArray: [MKDirections] = []
// ### code for directions end ###
override func viewDidLoad() {
super.viewDidLoad()
checkLocationServices()
setupMapView()
}
func setupMapView(){
mapView.delegate=self
}
func setupLocationManager() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
}
// helper function to display alerts to user
func displayAlert(alertTitle: String, alertMessage: String) {
let alert = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(alert, animated: true)
}
func centerViewOnUserLocation() {
if let location = locationManager.location?.coordinate {
let region = MKCoordinateRegion.init(center: location, latitudinalMeters: regionInMeters, longitudinalMeters: regionInMeters)
......@@ -41,18 +44,18 @@ class ViewController: UIViewController {
}
}
// check if user's location services are enabled
func checkLocationServices() {
if CLLocationManager.locationServicesEnabled() {
setupLocationManager()
checkLocationAuthorization()
} else {
// Show alert letting the user know they have to turn this on.
print("Location Services are not enabled")
displayAlert(alertTitle: "Location Services are not turned on", alertMessage: "You must enable your Location Services to perform this action")
}
}
// checking authorization status
func checkLocationAuthorization() {
let manager = CLLocationManager()
switch manager.authorizationStatus {
......@@ -76,29 +79,24 @@ class ViewController: UIViewController {
}
}
// ### code for directions start ###
func setupMapView(){
mapView.delegate=self
}
// action triggered on the "GO" button tap
@IBAction func goButtonTapped(_ sender: Any) {
print("GO button tapped")
getDirections()
}
func getLocationCoordinates() -> CLLocationCoordinate2D {
let cologne = MKPointAnnotation()
cologne.title = "Cologne"
cologne.coordinate = CLLocationCoordinate2D(latitude: 50.9375, longitude: 6.9603)
mapView.addAnnotation(cologne)
return cologne.coordinate //hard coded coordinates for Cologne
//to prevent throttling and multiple renders
func resetMapView(withNew directions: MKDirections) {
mapView.removeOverlays(mapView.overlays)
directionsArray.append(directions)
let _ = directionsArray.map { $0.cancel() }
}
// main function for routing
func getDirections() {
guard let location = locationManager.location?.coordinate else {
//TODO: Inform user we don't have their current location
print("Location not found")
displayAlert(alertTitle: "Location not found", alertMessage: "App cannot access your location")
return
}
......@@ -107,12 +105,21 @@ class ViewController: UIViewController {
resetMapView(withNew: directions)
directions.calculate { [unowned self] (response, error) in
//TODO: Handle error if needed
guard let response = response else { return } //TODO: Show response not available in an alert
if error != nil {
print("Directions couldn't be computed")
displayAlert(alertTitle: "Directions couldn't be computed", alertMessage: "App cannot find directions to the destination")
return
}
guard let response = response else {
print("Response not found")
displayAlert(alertTitle: "Directions couldn't be computed", alertMessage: "App cannot find directions to the destination")
return
}
print("total routes found: \(response.routes.count)")
for route in response.routes {
self.mapView.addOverlay(route.polyline, level: .aboveRoads)
var directionsRegion: MKCoordinateRegion = MKCoordinateRegion.init(route.polyline.boundingMapRect)
self.mapView.addOverlay(route.polyline, level: .aboveRoads) //add an overlay for each route
//polyline: connected line segments that don't form a loop
var directionsRegion: MKCoordinateRegion = MKCoordinateRegion.init(route.polyline.boundingMapRect) // recenter
//to increase the span of the region in order to add some margin
directionsRegion.span.latitudeDelta *= 1.2
directionsRegion.span.longitudeDelta *= 1.2
......@@ -121,31 +128,30 @@ class ViewController: UIViewController {
}
}
// creates a new request by configuring different properties
func createDirectionsRequest(from coordinate: CLLocationCoordinate2D) -> MKDirections.Request {
let destinationCoordinate = getLocationCoordinates()
let startingLocation = MKPlacemark(coordinate: coordinate) //user's location
let destination = MKPlacemark(coordinate: destinationCoordinate)
let request = MKDirections.Request()
request.source = MKMapItem(placemark: startingLocation)
request.destination = MKMapItem(placemark: destination)
request.transportType = .automobile
request.requestsAlternateRoutes = true
return request
}
//to prevent throttling and multiple renders
func resetMapView(withNew directions: MKDirections) {
mapView.removeOverlays(mapView.overlays)
directionsArray.append(directions)
let _ = directionsArray.map { $0.cancel() }
// hard-coded to return coordinates of Southampton
func getLocationCoordinates() -> CLLocationCoordinate2D {
let southampton = MKPointAnnotation()
southampton.title = "Southampton"
southampton.coordinate = CLLocationCoordinate2D(latitude: 50.9097, longitude: -1.4044)
mapView.addAnnotation(southampton) // add annotation(a pin) for Southampton
return southampton.coordinate
}
// ### code for directions end ###
}
extension ViewController: CLLocationManagerDelegate, MKMapViewDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
......@@ -158,7 +164,8 @@ extension ViewController: CLLocationManagerDelegate, MKMapViewDelegate {
checkLocationAuthorization()
}
// ### code for directions start ###
// called each time the bounding map rectangle of an overlay intersects the visible region of a map
// defines 'how' the overlay should look like -> renderer properties are specified here
func mapView(_ mapView: MKMapView,
rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
......@@ -168,22 +175,22 @@ extension ViewController: CLLocationManagerDelegate, MKMapViewDelegate {
return renderer
}
// Delegate method for annotations
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
guard annotation is MKPointAnnotation else { return nil }
let identifier = "Annotation"
// dequeue an existing annotation view before creating a new one as new annotations move on-screen
// (performance enhancement)
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView!.canShowCallout = true
} else {
annotationView!.annotation = annotation
}
return annotationView
}
// ### code for directions end ###
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment