MKOverlayRenderer function not being called? - swift

import UIKit
import CoreData
import Foundation
import MapKit
struct Geoshape : Codable {
let coordinates: [[Double]]
}
struct Field : Codable {
let geo_shape: Geoshape
let level_of_service: String
}
struct Record: Codable {
let fields: Field
}
struct Verkeer: Codable{
let records: Array<Record>
}
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate{
var managedContext:NSManagedObjectContext?
var coordinaten: [[[Double]]] = []
var levels: [String] = []
#IBOutlet weak var myMap: MKMapView!
let initialLocation = CLLocation(latitude: 50.841890, longitude: 4.323475)
override func viewDidLoad() {
super.viewDidLoad()
myMap.delegate = self
centerMapOnLocation(location: initialLocation)
}
#IBAction func clickRefresh(_ sender: Any) {
//Refresh -> array leegmaken en waardes opnieuw toevoegen in core data
coordinaten = []
levels = []
guard let url = URL(string: "https://opendata.brussels.be/api/records/1.0/search/?dataset=traffic-volume&rows=70&facet=level_of_service") else { return }
let session = URLSession.shared
let task = session.dataTask(with: url){ (data, response, error) in
if let response = response {
print(response)
}
if let data = data {
let traffic = try? JSONDecoder().decode(Verkeer.self, from: data)
let test = traffic?.records
for loop in test! {
//Coördinaten
//print(loop.fields.geo_shape.coordinates)
self.coordinaten.append(loop.fields.geo_shape.coordinates)
//Levels
//print(loop.fields.level_of_service)
self.levels.append(loop.fields.level_of_service)
}
var points = [MKMapPoint]()
for x in 0..<self.coordinaten.count{
for y in 0..<self.coordinaten[x].count{
print(self.coordinaten[x][y][0])
let p = MKMapPoint(CLLocationCoordinate2DMake(self.coordinaten[x][y][0], self.coordinaten[x][y][1]))
points.append(p)
}
let polyline = MKPolyline(points: points, count: points.count)
self.myMap.addOverlay(polyline)
points.removeAll()
print(points.count)
}
}
}
task.resume()
}
let regionRadius: CLLocationDistance = 200
func centerMapOnLocation(location: CLLocation) {
let coordinateRegion = MKCoordinateRegion(center: location.coordinate,
latitudinalMeters: regionRadius, longitudinalMeters: regionRadius)
myMap.setRegion(coordinateRegion, animated: true)
//Add pin
let pin: MKPointAnnotation = MKPointAnnotation()
pin.coordinate = CLLocationCoordinate2DMake(initialLocation.coordinate.latitude, initialLocation.coordinate.longitude);
pin.title = "Current location"
myMap.addAnnotation(pin)
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if overlay is MKPolyline {
let lineView = MKPolylineRenderer(overlay: overlay)
lineView.strokeColor = UIColor.red
lineView.lineWidth = 10
return lineView
}
return MKOverlayRenderer()
}
}
So I've been trying to show some coordinates on my map, but it does not seem to work. I get the coordinates from a json file and printing them is no problem but its the part where I try to add them to my map.. Anyone knows why this "func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer" is not being called? When I was searching online, the only thing I could find was to add the map delegate in viewDidLoad() function but that also does not work for me..

It’s because your overlay is not visible because the latitude and longitude are backwards. Swap them and you’ll start to see your overlays:
let coordinate = CLLocationCoordinate2DMake(self.coordinaten[x][y][1], self.coordinaten[x][y][0])

Related

How to replace new location coordinates in current location coordinates in MKMapView in swift

I am using map in Two viewcontrollers
Initially in first viewcontroller i am getting current location in map..
in second viewcontroller i am getting new location coordinates, which i am sending to firstview controller using delegate.. but here how to replace the delegate method coordinates with current location coordinates in first view controller
first view controller code: here in delegate method i am successfully having new location coordinates which i need replace with current location
in userDidEnterInformationdelegate method i am getting all values from 2nd view controller
import UIKit
import CoreLocation
import MapKit
class ProfileAddressViewController: UIViewController, CLLocationManagerDelegate, UISearchBarDelegate, DataEnteredDelegate {
var coordinate: CLLocationCoordinate2D = CLLocationCoordinate2D()
let locationManager = CLLocationManager()
var latitude: Double?
var logitude: Double?
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.requestAlwaysAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.startUpdatingLocation()
}
}
func userDidEnterInformation(info: DataEnteredModelSave) {
print("map address viewcontroller data \(info)")
self.pincodeField.text = info.pinCode
self.cityField.text = info.cityField
self.latitude = info.zLatitude
self.self.logitude = info.zLongitude
print("new map address viewcontroller data info lat long \(self.latitude) \(self.logitude)")
}
#IBAction func submitButtonClicked(_ sender: UIButton) {
self.view.endEditing(true)
let viewController = self.storyboard?.instantiateViewController(withIdentifier: "NewZoomAddressViewController") as! NewZoomAddressViewController;
self.navigationController?.pushViewController(viewController, animated: true);
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(error)
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let _: CLLocationCoordinate2D = manager.location?.coordinate else { return }
let userLocation :CLLocation = locations.last! as CLLocation
latitude = userLocation.coordinate.latitude
logitude = userLocation.coordinate.longitude
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(userLocation) { (placemarks, error) in
if (error != nil){
print("error in reverseGeocode")
}
let placemark = placemarks! as [CLPlacemark]
if placemark.count>0{
let placemark = placemarks![0]
let placemarkDictonary: NSDictionary=placemark.addressDictionary as! NSDictionary
self.pincodeField.text=placemarkDictonary["ZIP"] as? String
self.cityField.text=placemarkDictonary["City"] as? String
}
}
let center = CLLocationCoordinate2D(latitude: latitude!, longitude: logitude!)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
mapView.setRegion(region, animated: true)
let myAnnotation: MKPointAnnotation = MKPointAnnotation()
myAnnotation.coordinate = CLLocationCoordinate2DMake(userLocation.coordinate.latitude, userLocation.coordinate.longitude);
myAnnotation.title = "Current location"
mapView.addAnnotation(myAnnotation)
}
}
please help me to add delegate method latitude and longitude in locationManager didUpdateLocations
Replace userDidEnterInformation with below code:
func userDidEnterInformation(info: DataEnteredModelSave) {
print("map address viewcontroller data \(info)")
self.pincodeField.text = info.pinCode
self.streetField.text = info.streetField
self.cityField.text = info.cityField
self.latitude = info.zLatitude
self.logitude = info.zLongitude
print("map address viewcontroller data info lat long \(self.latitude) \(self.logitude)")
locationManager.stopUpdatingLocation() //stop updating location when you got data from delegate
let userLocation = CLLocation.init(latitude: latitude!, longitude: logitude!)
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(userLocation) { (placemarks, error) in
if (error != nil){
print("error in reverseGeocode")
}
let placemark = placemarks! as [CLPlacemark]
if placemark.count>0{
let placemark = placemarks![0]
print(placemark.locality!)
print(placemark.administrativeArea!)
print(placemark.country!)
let placemarkDictonary: NSDictionary=placemark.addressDictionary as! NSDictionary
self.pincodeField.text=placemarkDictonary["ZIP"] as? String
self.cityField.text=placemarkDictonary["City"] as? String
self.plotField.text=placemarkDictonary["Name"] as? String
self.streetField.text=placemarkDictonary["Street"] as? String
self.appormentNoField.text=placemarkDictonary["SubThoroughfare"] as? String
self.colonyField.text=placemarkDictonary["SubLocality"] as? String
self.landmarkField.text=placemarkDictonary["SubThoroughfare"] as? String
}
}
let center = CLLocationCoordinate2D(latitude: latitude!, longitude: logitude!)
//Assign data to map again with new location
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
mapView.setRegion(region, animated: true)
let myAnnotation: MKPointAnnotation = MKPointAnnotation()
myAnnotation.coordinate = CLLocationCoordinate2DMake(latitude!, logitude!)
myAnnotation.title = "Current location"
mapView.addAnnotation(myAnnotation)
}
I have added comments please check them.
EDIT: As per your second request if you want to show new coordinates on NewZoomAddressViewController first you need to pass coordinates to NewZoomAddressViewController in submitButtonClicked method like:
viewController.latestLocation = CLLocation.init(latitude: self.latitude!, longitude: self.logitude!)
then in NewZoomAddressViewController declare new var
var latestLocation: CLLocation?
and remove other code which is related to user's current location and final code will look like:
import UIKit
import MapKit
import CoreLocation
//import SwiftKeychainWrapper
protocol DataEnteredDelegate: class {
func userDidEnterInformation(info: DataEnteredModelSave)
}
class NewZoomAddressViewController: UIViewController {
#IBOutlet weak var oneBtnContainerView: UIView!
var latitudeZoom: Double?
var logitudeZoom: Double?
weak var delegate: DataEnteredDelegate? = nil
var zipName: String?
var localityName: String?
var sublocalityName: String?
var streetNumber: String?
var streetName: String?
let searchCont = UISearchController(searchResultsController: nil)
let annotation = MKPointAnnotation()
#IBOutlet weak var mapView: MKMapView!
#IBOutlet weak var addressLabel: UILabel!
let regionInMeters: Double = 10000
var previousLocation: CLLocation?
var latestLocation: CLLocation?
override func viewDidLoad() {
super.viewDidLoad()
print("in Zoom map VC")
mapView.delegate = self
addressLabel.text = "\(self.sublocalityName!) \(localityName!) \(self.zipName!)"
centerViewOnUserLocation()
}
#IBAction func backBtn(_ sender: Any) {
self.navigationController?.popViewController(animated: true)
}
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.navigationBar.isHidden=true
}
var viewController: UIViewController?
#IBAction func confirmBtn(_ sender: Any) {
guard
let zipName = zipName,
let sublocalityName = sublocalityName,
let localityName = localityName,
let lnatZ = latitudeZoom,
let longZ = logitudeZoom
else { return }
let enteredData = DataEnteredModelSave(pinCode: zipName, streetField: sublocalityName, cityField: localityName, zLatitude: lnatZ, zLongitude: longZ)
delegate?.userDidEnterInformation(info: enteredData)
self.navigationController?.popViewController(animated: true)
}
func centerViewOnUserLocation() {
if let location = latestLocation {
let region = MKCoordinateRegion.init(center: location.coordinate, latitudinalMeters: regionInMeters, longitudinalMeters: regionInMeters)
mapView.setRegion(region, animated: true)
}
}
func getCenterLocation(for mapView: MKMapView) -> CLLocation {
latitudeZoom = mapView.centerCoordinate.latitude
logitudeZoom = mapView.centerCoordinate.longitude
print("coordinates from zoom in func \(latitudeZoom), \(logitudeZoom)")
return CLLocation(latitude: latitudeZoom!, longitude: logitudeZoom!)
//print(CLLocation.self)
}
}
extension NewZoomAddressViewController: CLLocationManagerDelegate, UISearchBarDelegate {
// MARK:- Search Address
#IBAction func searchLocationButton(_ sender: Any) {
// let searchCont = UISearchController(searchResultsController: nil)
searchCont.searchBar.delegate = self
searchCont.searchBar.backgroundColor = .blue
present(searchCont, animated:true, completion:nil)
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
searchBar.resignFirstResponder()
dismiss(animated: true, completion: nil)
//create the search request
let searchReq = MKLocalSearch.Request()
searchReq.naturalLanguageQuery = searchBar.text
let activeSearch = MKLocalSearch(request: searchReq)
activeSearch.start { (response, error) in
UIApplication.shared.endIgnoringInteractionEvents()
if response == nil{
print("error")
}
else{
//remove annotation
//let annotations = self.mapView.annotations
// self.mapView.removeAnnotation(annotations as! MKAnnotation)
//getting data
let lat = response?.boundingRegion.center.latitude
let long = response?.boundingRegion.center.longitude
//create annotation
//let annotation = MKPointAnnotation()
self.annotation.title = searchBar.text
self.annotation.coordinate = CLLocationCoordinate2DMake(lat!, long!)
self.mapView.addAnnotation(self.annotation)
//zooming annotation
let coordinate: CLLocationCoordinate2D = CLLocationCoordinate2DMake(lat!, long!)
let span = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
let region = MKCoordinateRegion(center: coordinate, span: span)
self.mapView.setRegion(region, animated: true)
// Add below code to get search address
let geoCoder = CLGeocoder()
let location = CLLocation(latitude: lat!, longitude: long!)
geoCoder.reverseGeocodeLocation(location, completionHandler:
{
placemarks, error -> Void in
// Place details
guard let placeMark = placemarks?.first else { return }
// Location name
self.zipName = placeMark.postalCode
self.localityName = placeMark.locality
self.sublocalityName = placeMark.subLocality
self.streetNumber = placeMark.subThoroughfare
self.streetName = placeMark.thoroughfare
})
}
}
}
}
extension NewZoomAddressViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
let center = getCenterLocation(for: mapView)
let geoCoder = CLGeocoder()
guard let previousLocation = self.latestLocation else { return }
guard center.distance(from: previousLocation) > 50 else { return }
self.previousLocation = center
let userLocation :CLLocation = center as CLLocation
latitudeZoom = userLocation.coordinate.latitude
logitudeZoom = userLocation.coordinate.longitude
print("snajxhdwuidhwiuqhdxiqwjmdio \(latitudeZoom), \(logitudeZoom)")
geoCoder.reverseGeocodeLocation(center) { [weak self] (placemarks, error) in
guard let self = self else { return }
if let _ = error {
//TODO: Show alert informing the user
return
}
guard let placemark = placemarks?.first else {
//TODO: Show alert informing the user
return
}
self.streetNumber = placemark.subThoroughfare ?? ""
self.streetName = placemark.thoroughfare ?? ""
print("street number of zoom map \(self.streetName)")
self.localityName = placemark.locality ?? ""//locality
self.sublocalityName = placemark.subLocality ?? ""//locality
self.zipName = placemark.postalCode ?? ""//locality
DispatchQueue.main.async {
self.addressLabel.text = "\(self.streetNumber ?? "") \(self.streetName ?? "") \(self.sublocalityName ?? "") \(self.zipName ?? "") \(self.localityName ?? "")"
print("zzooom map location label \(self.addressLabel.text)")
}
}
}
}

add go button MapKit Swift

I am using MapKit. It draws the route between the two entered locations. But the go button does not appear. So he draws the route but doesn't describe how to go on the route. You can see in the photo. It puts the pins, but the Go to route button does not appear. How can I activate the go button?
class customPin: NSObject, MKAnnotation {
var coordinate: CLLocationCoordinate2D
var title: String?
var subtitle: String?
init(pinTitle:String, pinSubTitle:String, location:CLLocationCoordinate2D) {
self.title = pinTitle
self.subtitle = pinSubTitle
self.coordinate = location
}
}
class mapViewController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
let sourceLocation = CLLocationCoordinate2D(latitude:39.173209 , longitude: -94.593933)
let destinationLocation = CLLocationCoordinate2D(latitude:38.643172 , longitude: -90.177429)
let sourcePin = customPin(pinTitle: "Kansas City", pinSubTitle: "aa", location: sourceLocation)
let destinationPin = customPin(pinTitle: "St. Louis", pinSubTitle: "ddd", location: destinationLocation)
self.mapView.addAnnotation(sourcePin)
self.mapView.addAnnotation(destinationPin)
let sourcePlaceMark = MKPlacemark(coordinate: sourceLocation)
let destinationPlaceMark = MKPlacemark(coordinate: destinationLocation)
let directionRequest = MKDirections.Request()
directionRequest.source = MKMapItem(placemark: sourcePlaceMark)
directionRequest.destination = MKMapItem(placemark: destinationPlaceMark)
directionRequest.transportType = .automobile
let directions = MKDirections(request: directionRequest)
directions.calculate { (response, error) in
guard let directionResonse = response else {
if let error = error {
print("we have error getting directions==\(error.localizedDescription)")
}
return
}
let route = directionResonse.routes[0]
self.mapView.addOverlay(route.polyline, level: .aboveRoads)
let rect = route.polyline.boundingMapRect
self.mapView.setRegion(MKCoordinateRegion(rect), animated: true)
}
self.mapView.delegate = self
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.blue
renderer.lineWidth = 4.0
return renderer
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Polyline not showing in MapKit [Xcode 9.0 - Swift 4.0]

Ive made a view controller which tracks my location once the view is opened. Once the routeButton is pressed, I want the blue Polyline to show. However it does not. Ive set the delegates and wrote the rendering function but it still does not show. I don't get an error when calculating directions. It does run the self.map.add(route.polyline, level: .aboveRoads) line. But no polyline is added to the map.
Ive read multiple questions relating to this on here, but nothing fixes my issue.
Any help would be greatly appreciated.
Heres my code:
class ThirdViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate{
var startLocCoord = CLLocation()
var endLocCoord = CLLocation()
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
let span:MKCoordinateSpan = MKCoordinateSpanMake(0.05,0.05)
let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude,location.coordinate.longitude)
let region:MKCoordinateRegion = MKCoordinateRegionMake(myLocation, span)
map.setRegion(region, animated: true)
self.map.showsUserLocation = true
}
#IBAction func routeButton (_ sender: Any) {
let destinationLoc = CLLocationCoordinate2D(latitude: endLocCoord.coordinate.latitude, longitude: endLocCoord.coordinate.longitude)
let sourceLoc = CLLocationCoordinate2D(latitude: startLocCoord.coordinate.latitude, longitude: startLocCoord.coordinate.longitude)
let sourcePlaceMark = MKPlacemark(coordinate: sourceLoc)
let destinationPlaceMark = MKPlacemark(coordinate: destinationLoc)
let directionRequest = MKDirectionsRequest()
directionRequest.source = MKMapItem(placemark: sourcePlaceMark)
directionRequest.destination = MKMapItem(placemark: destinationPlaceMark)
directionRequest.transportType = .automobile
let directions = MKDirections(request: directionRequest)
directions.calculate { (response, error) in
guard let directionResponse = response else {
if let error = error {
print("Error with directions==\(error.localizedDescription)")
}
return
}
let route = directionResponse.routes[0]
print("route ------->", route)
self.map.add(route.polyline, level: .aboveRoads)
let rect = route.polyline.boundingMapRect
self.map.setRegion(MKCoordinateRegionForMapRect(rect), animated: true)
print(self.srcLat, self.srcLon, self.lat, self.long)
}
override func viewDidLoad() {
manager.desiredAccuracy = kCLLocationAccuracyBest
UIApplication.shared.isIdleTimerDisabled = true
manager.delegate = self
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
manager.allowsBackgroundLocationUpdates = true
manager.pausesLocationUpdatesAutomatically = false
self.map.isZoomEnabled = false
self.map.isScrollEnabled = false
self.map.delegate = self
map.mapType = MKMapType.standard
}
func mapView(_mapView: MKMapView, rendererFor overlay: MKOverlay)-> MKOverlayRenderer{
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.blue
renderer.lineWidth = 5.0
print("render called")
return renderer
}
}
Thanks
It's probably just a typo. Replace
func mapView(_mapView: MKMapView, rendererFor overlay: MKOverlay)-> MKOverlayRenderer{
with
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {

Route Between two A and B location

There is no error but I can not get the location from my current location to what I search. Can someone please help. It says this with I click on the Car logo to get directions: MKDirectionsErrorCode=7, NSLocalizedDescription=Directions Not Available}
I am only missing the line to get to the direction. When I click on the car logo, it just does not do anything but zoom out to my current location. I am missing anything or did something wrong?
Here is my code:
protocol HandleMapSearch {
func dropPinZoomIn(placemark:MKPlacemark)
}
class ViewController: UIViewController {
#IBOutlet weak var mapView: MKMapView! // Handle the Map Kit View
var selectedPin:MKPlacemark? = nil //Any incoming placemarks
// Destination for directions*********
var destination:MKMapItem = MKMapItem()
var MyPosition = CLLocationCoordinate2D()
var resultSearchController:UISearchController? = nil // Keep the UISearchController in memory after it's created
var locationManager = CLLocationManager() // Core Location
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest // Accuracy level
locationManager.requestWhenInUseAuthorization() // Triggers the location permission dialog
locationManager.startUpdatingLocation()
//locationManager.requestLocation() // Trigers a one-time location request
// Set up the search results table
let locationSearchTable = storyboard!.instantiateViewController(withIdentifier: "LocationSearchTable") as! LocationSearchTable
resultSearchController = UISearchController(searchResultsController: locationSearchTable)
resultSearchController?.searchResultsUpdater = locationSearchTable
// Set up the search bar
let searchBar = resultSearchController!.searchBar
searchBar.sizeToFit()
searchBar.placeholder = "Search for places"
navigationItem.titleView = resultSearchController?.searchBar
// Configure the UISearchController appearance
resultSearchController?.hidesNavigationBarDuringPresentation = false
resultSearchController?.dimsBackgroundDuringPresentation = true
definesPresentationContext = true
locationSearchTable.mapView = mapView // Passes along a handle of the mapView
locationSearchTable.handleMapSearchDelegate = self // Handles the map search
}
//Getting direction of location
#objc func getDirections(sender: AnyObject){
if let selectedPin = selectedPin {
let mapItem = MKMapItem(placemark: selectedPin)
//let launchOptions = [MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving]
//mapItem.openInMaps(launchOptions: launchOptions)
let request = MKDirectionsRequest()
request.source = MKMapItem.forCurrentLocation()
request.destination = destination
request.requestsAlternateRoutes = false
let directions = MKDirections(request: request)
// 8.
directions.calculate {
(response, error) -> Void in
guard let response = response else {
if let error = error {
print("Error: \(error)")
}
return
}
let route = response.routes[0]
self.mapView.add((route.polyline), level: MKOverlayLevel.aboveRoads)
let rect = route.polyline.boundingMapRect
self.mapView.setRegion(MKCoordinateRegionForMapRect(rect), animated: true)
}
}
/*
directions.calculate(completionHandler: {(response: MKDirectionsResponse!, error: Error!) in
if error != nil {
print("Error \(error)")
} else {
self.displayRout(response)
var overlays = self.mapView.overlays
for route in response.routes {
self.mapView.add(route.polyline, level: MKOverlayLevel.aboveRoads)
for next in route.steps {
print(next.instructions)
}
}
}
})
}
*/
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.blue
renderer.lineWidth = 4.0
return renderer
}
}
//destination = MKMapItem(placemark: selectedPin!)
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension ViewController : CLLocationManagerDelegate {
// When user responds to the permission dialog
private func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse {
locationManager.requestLocation()
}
}
// When location information comes back (Zoom to the user's current location)
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
//****
MyPosition = location.coordinate
locationManager.stopUpdatingLocation()
let span = MKCoordinateSpanMake(0.01, 0.01)
let region = MKCoordinateRegion(center: location.coordinate, span: span)
mapView.setRegion(region, animated: true)
}
}
// Print out the error
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Error finding location: \(error.localizedDescription)")
}
}
// Searches the location and city/state
extension ViewController: HandleMapSearch {
func dropPinZoomIn(placemark:MKPlacemark){
// cache the pin
selectedPin = placemark
// clear existing pins
mapView.removeAnnotations(mapView.annotations)
let annotation = MKPointAnnotation()
annotation.coordinate = placemark.coordinate
annotation.title = placemark.name
if let city = placemark.locality,
let state = placemark.administrativeArea {
annotation.subtitle = "\(city) \(state)"
}
mapView.addAnnotation(annotation)
let span = MKCoordinateSpanMake(0.01, 0.01)
let region = MKCoordinateRegionMake(placemark.coordinate, span)
mapView.setRegion(region, animated: true)
}
}
// Shows Pins and Car Logo
extension ViewController : MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?{
if annotation is MKUserLocation {
//return nil so map view draws "blue dot" for standard user location
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKPinAnnotationView
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.pinTintColor = UIColor.red
pinView?.canShowCallout = true
let smallSquare = CGSize(width: 30, height: 30)
let button = UIButton(frame: CGRect(origin: CGPoint.zero, size: smallSquare))
button.setBackgroundImage(UIImage(named: "Car"), for: .normal)
button.addTarget(self, action: #selector(getDirections), for: .touchUpInside)
pinView?.leftCalloutAccessoryView = button
return pinView
}
}
Have a look at below code for reference hope it helps :
1 using two locations here as source and as destination and drawing a path according to locations
import UIKit
import CoreLocation
import MapKit
class ViewController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
// Do any additional setup after loading the view, typically from a nib.
let sourceLocation = CLLocationCoordinate2D(latitude: 40.759011, longitude: -73.984472)
let destinationLocation = CLLocationCoordinate2D(latitude: 40.748441, longitude: -73.985564)
// 3.
let sourcePlacemark = MKPlacemark(coordinate: sourceLocation, addressDictionary: nil)
let destinationPlacemark = MKPlacemark(coordinate: destinationLocation, addressDictionary: nil)
// 4.
let sourceMapItem = MKMapItem(placemark: sourcePlacemark)
let destinationMapItem = MKMapItem(placemark: destinationPlacemark)
// 5.
let sourceAnnotation = MKPointAnnotation()
sourceAnnotation.title = "Times Square"
if let location = sourcePlacemark.location {
sourceAnnotation.coordinate = location.coordinate
}
let destinationAnnotation = MKPointAnnotation()
destinationAnnotation.title = "Empire State Building"
if let location = destinationPlacemark.location {
destinationAnnotation.coordinate = location.coordinate
}
// 6.
self.mapView.showAnnotations([sourceAnnotation,destinationAnnotation], animated: true )
// 7.
let directionRequest = MKDirectionsRequest()
directionRequest.source = sourceMapItem
directionRequest.destination = destinationMapItem
directionRequest.transportType = .walking
// Calculate the direction
let directions = MKDirections(request: directionRequest)
// 8.
directions.calculate {
(response, error) -> Void in
guard let response = response else {
if let error = error {
print("Error: \(error)")
}
return
}
let route = response.routes[0]
self.mapView.add((route.polyline), level: MKOverlayLevel.aboveRoads)
let rect = route.polyline.boundingMapRect
self.mapView.setRegion(MKCoordinateRegionForMapRect(rect), animated: true)
}
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.blue
renderer.lineWidth = 4.0
return renderer
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Output :

Converting Parse PFGeoPoint into an annotation on the map

I am trying to convert a saved PFGeopoint objects in Parse server into an annotation but i can't seem to figure it out and i don't know what's wrong.
I tried to apply the code from this question : Converting Parse GeoPoint into a CLLocation in Swift but i still couldn't figure it out.
Here is my Code :
import UIKit
import MapKit
import CoreLocation
import Parse
class MapVC: UIViewController, MKMapViewDelegate {
fileprivate let locationManager = CLLocationManager()
fileprivate var startedLoadingPOIs = false
fileprivate var places = [Place]()
var descLocation: PFGeoPoint = PFGeoPoint()
var mapHasCenteredOnce = false
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
locationManager.startUpdatingLocation()
locationManager.requestWhenInUseAuthorization()
mapView.userTrackingMode = MKUserTrackingMode.followWithHeading
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
var annotationView: MKAnnotationView?
if annotation.isKind(of: MKUserLocation.self) {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "User")
annotationView?.image = UIImage(named: "loc.png")
}
return annotationView
}
}
extension MapVC: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//1
if locations.count > 0 {
let location = locations.last!
print("Accuracy: \(location.horizontalAccuracy)")
//2
if location.horizontalAccuracy < 100 {
//3
manager.stopUpdatingLocation()
let span = MKCoordinateSpan(latitudeDelta: 0.014, longitudeDelta: 0.014)
let region = MKCoordinateRegion(center: location.coordinate, span: span)
mapView.region = region
if !startedLoadingPOIs {
startedLoadingPOIs = true
let loader = PlacesLoader()
loader.loadPOIS(location: location, radius: 1000) { placesDict, error in
if let dict = placesDict {
let query = PFQuery(className: "posts")
if let latitude = (PFUser.current()?["location"] as AnyObject).latitude {
if let longitude = (PFUser.current()?["location"] as AnyObject).longitude {
let geoPoint = PFGeoPoint(latitude: latitude, longitude: longitude)
query.whereKey("postLocation", nearGeoPoint: geoPoint, withinKilometers: 1)
}
}
query.findObjectsInBackground { (objects: [PFObject]?, error: Error?) in
if error == nil {
for object in objects! {
let pfObject = object as PFObject
let caption = pfObject["title"] as! String
self.descLocation = object["postLocation"] as! PFGeoPoint
let latitude: CLLocationDegrees = self.descLocation.latitude
let longitude: CLLocationDegrees = self.descLocation.longitude
let location = CLLocation(latitude: latitude, longitude: longitude)
let place = Place(location: location, name: caption )
self.places.append(place)
let annotation = PlaceAnnotation(location: place.location!.coordinate, title: place.placeName)
DispatchQueue.main.async {
self.mapView.addAnnotation(annotation)
}
}
}
}
}
}
}
}
}
}
}
I just had two uanessacry lines that blocked the operation, removed them and it worked for me.
loader.loadPOIS(location: location, radius: 1000) { placesDict, error in
if let dict = placesDict {