This is what my ViewController.swift looks like
import UIKit
import MapKit
import CoreLocation
import Parse
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate, UISearchBarDelegate {
@IBOutlet weak var LiveMap: MKMapView!
private weak var searchController: SearchViewController?
var officesCopy = [OfficeStats]()
var officesNameCopy = [String]()
var annotationName = ""
let queriesClass = Queries()
let manager = CLLocationManager()
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.hideKeyboardWhenTappedAround()
manager.desiredAccuracy = kCLLocationAccuracyReduced // Affects battery life
manager.delegate = self
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
loadPins()
}
func setUpNavBar() {
let searchBar = UISearchBar()
searchBar.delegate = self
searchBar.sizeToFit()
searchBar.searchBarStyle = .minimal
searchBar.placeholder = "Kërko"
searchBar.tintColor = UIColor.lightGray
searchBar.barTintColor = UIColor.lightGray
navigationItem.titleView = searchBar
searchBar.isTranslucent = true
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
self.present(UINavigationController(rootViewController: SearchViewController()), animated: false, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
let searchController = SearchViewController()
searchController.selectionDelegate = self
setUpNavBar()
self.LiveMap.delegate = self
self.navigationItem.largeTitleDisplayMode = .never
retrieveNameCopy() { (success, offices) in
if success {
// self.officesNameCopy.sort {$0 < $1}
} else {
print("unsuceess")
}
}
loadPins()
bashkiaReposition(self)
NotificationCenter.default
.addObserver(self,
selector: #selector(statusManager),
name: .flagsChanged,
object: nil)
updateUserInterface()
}
func retrieveNameCopy(completion: @escaping (_ success: Bool, _ elements: [String]) -> Void) {
let queries = PFQuery(className: "Drejtori")
queries.fromLocalDatastore()
queries.findObjectsInBackground { (object, error) in
if let error = error {
// The query failed
print(error.localizedDescription)
completion(false, [])
} else if let object = object {
// The query succeeded with a matching result
for i in object{
self.officesCopy.append(OfficeStats(name: i["name"] as! String, phone: i["phone"] as? String ?? "", location: i["location"] as? String ?? "", website: i["website"] as? String ?? "", coordinates: PFGeoPoint(latitude: (i["coordinates"] as! PFGeoPoint).latitude, longitude: (i["coordinates"] as! PFGeoPoint).longitude), email: i["email"] as? String ?? "", short_description: i["short_description"] as? String ?? "", long_description: i["long_description"] as? String ?? ""))
self.officesNameCopy.append(i["name"] as! String)
}
completion(true, self.officesNameCopy)
} else {
completion(true, [])
// The query succeeded but no matching result was found
}
}
}
func sortList() { // should probably be called sort and not filter
officesCopy.sort { $0.name < $1.name } // sort the fruit by name
}
func updateUserInterface() {
switch Network.reachability.status {
case .unreachable:
print("Unreachable")
case .wwan:
queriesClass.updateQueries()
queriesClass.saveAllQueriesLocally()
case .wifi:
queriesClass.updateQueries()
queriesClass.saveAllQueriesLocally()
}
print("Reachability Summary")
print("Status:", Network.reachability.status)
print("HostName:", Network.reachability.hostname ?? "nil")
print("Reachable:", Network.reachability.isReachable)
print("Wifi:", Network.reachability.isReachableViaWiFi)
}
@objc func statusManager(_ notification: Notification) {
updateUserInterface()
}
func loadPins() {
let localQuery = PFQuery(className: "Drejtori")
localQuery.fromLocalDatastore()
localQuery.findObjectsInBackground { (objects, error) -> Void in
if error == nil {
if let returnedobjects = objects {
for object in returnedobjects {
//Declaring coordinates
let userGeoPoint = object["coordinates"] as? PFGeoPoint
let annotation = MKPointAnnotation()
annotation.title = object["name"] as? String
annotation.subtitle = object["location"] as? String
//Adding coordinates and pins to the map
annotation.coordinate = CLLocationCoordinate2D(latitude: userGeoPoint?.latitude ?? 0, longitude: userGeoPoint?.longitude ?? 0)
self.LiveMap.addAnnotation(annotation)
self.LiveMap.delegate = self
}
}
}
}
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.systemBlue
renderer.lineWidth = 5.0
return renderer
}
func showRouteOnMap(pickupCoordinate: CLLocationCoordinate2D, destinationCoordinate: CLLocationCoordinate2D) {
let request = MKDirections.Request()
request.source = MKMapItem(placemark: MKPlacemark(coordinate: pickupCoordinate, addressDictionary: nil))
request.destination = MKMapItem(placemark: MKPlacemark(coordinate: destinationCoordinate, addressDictionary: nil))
request.requestsAlternateRoutes = true
request.transportType = .automobile
let directions = MKDirections(request: request)
directions.calculate { [unowned self] response, error in
guard let unwrappedResponse = response else { return }
//for getting just one route
if let route = unwrappedResponse.routes.first {
//show on map
self.LiveMap.addOverlay(route.polyline)
//set the map area to show the route
self.LiveMap.setVisibleMapRect(route.polyline.boundingMapRect, edgePadding: UIEdgeInsets.init(top: 80.0, left: 20.0, bottom: 100.0, right: 20.0), animated: true)
}
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
manager.stopUpdatingLocation()
render(location)
}
}
func render(_ location: CLLocation) {
let coordinate = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
let span = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
let _ = MKCoordinateRegion(center: coordinate, span: span)
//LiveMap.setRegion(region, animated: true)
self.LiveMap.showsUserLocation = true
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
print(searchText)
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "customannotation")
annotationView.image = UIImage(named:"logoBashkia")
annotationView.canShowCallout = true
let button = UIButton(type: UIButton.ButtonType.detailDisclosure) as UIButton // button with info sign in it
annotationView.rightCalloutAccessoryView = button
return annotationView
}
func indexOfTap() -> Int{
var indexOfOffice = 0
for (index, element) in officesNameCopy.enumerated(){
if element == annotationName {
indexOfOffice = index
}
}
return indexOfOffice
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == view.rightCalloutAccessoryView{
print(view.annotation?.title!! as Any) // your annotation's title
//Perform a segue here to navigate to another viewcontroller
annotationName = view.annotation?.title!! ?? ""
performSegue(withIdentifier: "showPopoverDetail", sender: self)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? OfficeDetailViewController {
destination.office = officesCopy[(indexOfTap())]
}
}
@IBAction func relocation(_ sender: Any) {
let region: MKCoordinateRegion = MKCoordinateRegion(center: LiveMap.userLocation.coordinate, span: LiveMap.region.span)
LiveMap.setRegion(region, animated: true)
}
@IBAction func bashkiaReposition(_ sender: Any) {
let query = PFQuery(className: "Drejtori")
query.whereKey("name", equalTo:"Bashkia Tiranë")
query.fromLocalDatastore()
query.findObjectsInBackground { (objects: [PFObject]?, error: Error?) in
if let error = error {
// Log details of the failure
print(error.localizedDescription)
} else if let objects = objects {
//The find succeeded.
print("Successfully retrieved \(objects.count) scores.")
for object in objects {
//print(object.objectId as Any)
//Setting default location for Bashkia Tiranës
let userGeoPoint = object["coordinates"] as! PFGeoPoint
let location = CLLocationCoordinate2D(latitude: userGeoPoint.latitude, longitude:userGeoPoint.longitude)
let region = MKCoordinateRegion(center: location, span: MKCoordinateSpan(latitudeDelta: 0.005, longitudeDelta: 0.005))
//Redirecting the map to Bashkia Tiranë
if self.LiveMap != nil{
self.LiveMap.setRegion(region, animated: true)
}
}
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
extension UIViewController {
func hideKeyboardWhenTappedAround() {
let tap = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
tap.cancelsTouchesInView = true
view.addGestureRecognizer(tap)
}
@objc func dismissKeyboard() {
view.endEditing(true)
}
}
extension ViewController: SelectionCoordinateDelegate {
func didTapChoice(_ searchController: SearchViewController, coordinates: CLLocationCoordinate2D) {
let latCoord = coordinates.latitude
let longCoord = coordinates.longitude
let location = CLLocationCoordinate2D(latitude: latCoord, longitude:longCoord)
let region = MKCoordinateRegion(center: location, span: MKCoordinateSpan(latitudeDelta: 0.005, longitudeDelta: 0.005))
self.LiveMap.setRegion(region, animated: true)
}
}