Navigation from user location to annotation - ios

so I want to set up a map with navigation from the users location to a annotation that the user selected. I Have all the annotations loaded from a .Plist . someone help me out I'm just a beginner. this is my code for the map:
import UIKit
import MapKit
import CoreLocation
class MapViewController: UIViewController, CLLocationManagerDelegate, UISearchBarDelegate {
#IBOutlet weak var mapView: MKMapView!
#IBAction func searchButton(_ sender: Any) {
let searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.delegate = self
present(searchController, animated: true, completion: nil)
}
let locationManager = CLLocationManager()
// Vraag om locatie van gebruiker
func requestLocationAccess()
{
let status = CLLocationManager.authorizationStatus()
switch status
{
case .authorizedAlways, .authorizedWhenInUse:
return
case .denied, .restricted:
print("location access denied")
default:
locationManager.requestWhenInUseAuthorization()
}
}
class func createViewAnnotationForMap(mapView:MKMapView, annotation:MKAnnotation)->MKAnnotationView
{
if let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "PinAnnotation"){
return annotationView
}
else
{
let returnedAnnotationView:MKPinAnnotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier:"PinAnnotation")
returnedAnnotationView.animatesDrop = false
returnedAnnotationView.canShowCallout = true
return returnedAnnotationView
}
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar)
{
//Ignoring user
UIApplication.shared.beginIgnoringInteractionEvents()
//Activity Indicator
let activityIndicator = UIActivityIndicatorView()
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
activityIndicator.center = self.view.center
activityIndicator.hidesWhenStopped = true
activityIndicator.startAnimating()
self.view.addSubview(activityIndicator)
//Hide search bar
searchBar.resignFirstResponder()
dismiss(animated: true, completion: nil)
//Create the search request
let searchRequest = MKLocalSearchRequest()
searchRequest.naturalLanguageQuery = searchBar.text
let activeSearch = MKLocalSearch(request: searchRequest)
activeSearch.start { (response, error) in
activityIndicator.stopAnimating()
UIApplication.shared.endIgnoringInteractionEvents()
if response == nil
{
print("ERROR")
}
else
{
//Getting data
let latitude = response?.boundingRegion.center.latitude
let longitude = response?.boundingRegion.center.longitude
//Create annotation
let annotation = MKPointAnnotation()
annotation.title = searchBar.text
annotation.coordinate = CLLocationCoordinate2DMake(latitude!, longitude!)
self.mapView.addAnnotation(annotation)
//Zooming in on annotation
let coordinate:CLLocationCoordinate2D = CLLocationCoordinate2DMake(latitude!, longitude!)
let span = MKCoordinateSpanMake(0.1, 0.1)
let region = MKCoordinateRegionMake(coordinate, span)
self.mapView.setRegion(region, animated: true)
}
}
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(polyline: overlay as! MKPolyline)
renderer.strokeColor = UIColor.blue
return renderer
}
override func viewDidLoad()
{
super.viewDidLoad()
requestLocationAccess()
mapView.isZoomEnabled = true
mapView.isScrollEnabled = true
mapView.showsScale = true
mapView.isRotateEnabled = true
mapView.showsUserLocation = true
mapView.showsCompass = true
mapView.delegate = self
//Regio instellen
var newRegion:MKCoordinateRegion = MKCoordinateRegion()
newRegion.center.latitude = -25.106303;
newRegion.center.longitude = 133.587542;
newRegion.span.latitudeDelta = 22;
newRegion.span.longitudeDelta = 22;
self.mapView.setRegion(newRegion, animated: true)
if let cityDetailsPath = Bundle.main.path(forResource: "places", ofType: "plist") {
guard let cityDetails = NSArray(contentsOfFile: cityDetailsPath) as? [[String: String]] else {return}
for city in cityDetails
{
guard let latStr = city["latitude"] else { continue }
guard let lonStr = city["longitude"] else { continue }
guard let titleStr = city["title"] else { continue }
guard let subtitleStr = city["subTitle"] else { continue }
if let lat = Double(latStr) {
if let lon = Double(lonStr) {
let annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2DMake(lat,lon)
annotation.title = titleStr
annotation.subtitle = subtitleStr
mapView.addAnnotation(annotation)
}
}
}
}
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
}
extension MapViewController: MKMapViewDelegate {
func createViewAnnotationForMap(mapView:MKMapView, annotation:MKAnnotation)->MKAnnotationView {
let annoannotationId = "PinAnnotation"
if let annotationView = self.mapView.dequeueReusableAnnotationView(withIdentifier: annoannotationId) {
return annotationView
}
else
{
let returnedAnnotationView:MKPinAnnotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: annoannotationId)
returnedAnnotationView.animatesDrop = false
returnedAnnotationView.canShowCallout = true
return returnedAnnotationView
}
}
}

Use didSelect delegate method.
e.g.
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
guard let annotation = view.annotation else {
return
}
let directionRequest = MKDirectionsRequest()
directionRequest.source = MKMapItem.forCurrentLocation()
directionRequest.destination = MKMapItem(placemark: MKPlacemark(coordinate: annotation.coordinate))
directionRequest.transportType = .automobile
let directions = MKDirections(request: directionRequest)
directions.calculate {
(response, error) -> Void in
guard let response = response else {
if let error = error {
print("Error: \(error)")
}
return
}
if !response.routes.isEmpty {
let route = response.routes[0]
DispatchQueue.main.async { [weak self] in
self?.mapView.add(route.polyline)
}
}
}
}
Don't forget guard to prevent crash.
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) ->
MKOverlayRenderer {
guard overlay is MKPolyline else {
return MKPolylineRenderer()
}
...
}

Related

Making a phone call with swift not working with certain numbers

I have been trying desperately for the past few hours to make a phone call with swift when I call this function.
func callPhone(phoneNumber: String){
guard let url = URL(string:"telprompt:\(phoneNumber)") else {
print("failed to load url, phone number: \(phoneNumber)")
return
}
UIApplication.shared.open(url)
}
For some reason it doesn't work, I have researched online everywhere and still couldn't find a problem to why this wouldn't work. Some numbers would occasionally work, like if I tried "123456789" it would work. but if i try a different number it wouldn't work; The guard let statement doesn't work and the url would be empty.
Please help me. Any feedback would be very much appreciated.
Edit: So I found out when it is not working but I am not sure how to solve it. It doesn't work when I get the phone number from apple maps, but when I hard code the phone number it works.
Here is my full code:
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
#IBOutlet weak var map: MKMapView!
let locationManager = CLLocationManager()
let regionMeters : Double = 10000
override func viewDidLoad() {
super.viewDidLoad()
map.delegate = self
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
map.showsUserLocation = true
if let location = locationManager.location?.coordinate {
let region = MKCoordinateRegion.init(center: location, latitudinalMeters: regionMeters, longitudinalMeters: regionMeters)
map.setRegion(region, animated: true)
}
searchLocations(search: "Restaurant")
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "Place"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
if annotationView == nil {
annotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView!.canShowCallout = true
let btn = UIButton(type: .contactAdd)
annotationView!.rightCalloutAccessoryView = btn
} else {
annotationView!.annotation = annotation
}
return annotationView
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
let subtitle = view.annotation?.subtitle as! String
let splitted = subtitle.components(separatedBy: "+")
let number = splitted.last as! String
let trimmedNumber : String = number.components(separatedBy: [" ", "-", "(", ")"]).joined()
CallOnPhone(phoneNumber: trimmedNumber)
}
func searchLocations(search : String){
let searchRequest = MKLocalSearch.Request()
searchRequest.naturalLanguageQuery = search
searchRequest.region = map.region
let activeSearch = MKLocalSearch(request: searchRequest)
activeSearch.start { (response, err) in
if response == nil {
print("no request")
} else {
for item in (response?.mapItems)!{
let annotation = MKPointAnnotation()
annotation.title = item.name
if let phone = item.phoneNumber {
annotation.subtitle = "Phone Number: \(phone as String)"
}
annotation.coordinate = item.placemark.coordinate
self.map.addAnnotation(annotation)
}
}
}
}
#objc func CallOnPhone(phoneNumber: String){
let newStringPhone = phoneNumber.replacingOccurrences(of: " ", with: "", options: .literal, range: nil)
print(newStringPhone)
if newStringPhone != ""{
if let url = URL(string: "tel://\(newStringPhone)"), UIApplication.shared.canOpenURL(url) {
if #available(iOS 10, *) {
UIApplication.shared.open(url)
} else {
UIApplication.shared.openURL(url)
}
}
}
}
}
Thanks,
Try trimming the phone number.
let myphone:String = phoneNumber.trimmingCharacters(in:.whitespacesAndNewlines)
Full code:
if let url = URL(string: "tel://\(myphone)"),UIApplication.shared.canOpenURL(url) {
if #available(iOS 10, *) {
UIApplication.shared.open(url, options: [:], completionHandler:nil)
} else {
UIApplication.shared.openURL(url)
}
} else {
Util.shared.showToast(message: "Can't make call from this device", view: self.view)
}
Below code show calling a number on button click. Also removing space if phonenum has spaces.
var phoneNumber = "Phone Number: 1234567"
var finalNumber = ""
let number = phoneNumber.split(separator: ":")
let tempNum = "\(number.last ?? "")"
print(tempNum)
let trimmedNumber : String = tempNum.components(separatedBy: [" ", "-", "(", ")"]).joined()
print(trimmedNumber)
finalNumber = trimmedNumber
print(finalNumber)
btn_Call.addTarget(self, action: #selector(CallOnPhone), for: .touchUpInside)
#objc func CallOnPhone(sender:UIButton){
let newStringPhone = finalNumber.replacingOccurrences(of: " ", with: "", options: .literal, range: nil)
print(newStringPhone)
if newStringPhone != ""{
if let url = URL(string: "tel://\(newStringPhone)"), UIApplication.shared.canOpenURL(url) {
if #available(iOS 10, *) {
UIApplication.shared.open(url)
} else {
UIApplication.shared.openURL(url)
}
}
}
}

locationManager Unwrapping Error in Swift 4.1 but not in Swift 4.0

I have code that I wrote in Swift 4.0 allowing an App which I am working on to show a Map with a destination and a user location. Now this app worked perfectly before the the recent update to Swift 4.1.
The error message says that there is an unexpectedly found nil while unwrapping an Optional value. In the xCode output window it is showing the following text:
Could not inset legal attribution from corner 4
(lldb)
I have tried all sorts of things, and looked this up all over the internet and I am not sure wether this is a bug in Swift 4.1 or there is something new I need to do. Like said, this app worked perfectly before.
I also made sure the info.plist has the right Privacy properties applied for Location Manager.
Info.plist
import UIKit
import MapKit
import CoreLocation
class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBAction func centerUserLocation(_ sender: Any) {
mapkitView.setUserTrackingMode(MKUserTrackingMode.follow, animated: true)
}
#IBOutlet weak var mapkitView: MKMapView!
let locationManager = CLLocationManager()
#IBAction func phoneNumber(_ sender: Any) {
let number = "00436641491000"
if let url = URL(string: "tel://\(number)") {
UIApplication.shared.open(url)
}
}
#IBAction func emailAddress(_ sender: Any) {
let email = "salzburg#citybeats.at"
if let url = URL(string: "mailto:\(email)") {
UIApplication.shared.open(url)
}
}
override func viewDidLoad() {
super.viewDidLoad()
mapkitView.delegate = self
mapkitView.showsScale = true
mapkitView.showsPointsOfInterest = true
mapkitView.showsUserLocation = true
mapkitView.userTrackingMode = .follow
locationManager.requestAlwaysAuthorization()
locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled(){
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
let sourceCoordinates = locationManager.location?.coordinate
let destCoordinates = CLLocationCoordinate2DMake(47.800715, 13.041061)
let sourcePlacemark = MKPlacemark(coordinate: sourceCoordinates!)
let destPlacemark = MKPlacemark(coordinate: destCoordinates)
let annotation = MKPointAnnotation()
annotation.coordinate = destCoordinates
annotation.title = "CityBeats"
annotation.subtitle = "House & RnB"
mapkitView.addAnnotation(annotation)
let sourceItem = MKMapItem(placemark: sourcePlacemark)
let destItem = MKMapItem(placemark: destPlacemark)
let directionRequest = MKDirectionsRequest()
directionRequest.source = sourceItem
directionRequest.destination = destItem
directionRequest.transportType = .walking
let directions = MKDirections(request: directionRequest)
directions.calculate(completionHandler: {
response, error in
guard let response = response else {
if let error = error {
print("Something went wrong!")
}
return
}
let route = response.routes[0]
self.mapkitView.add(route.polyline, level: .aboveRoads)
let rekt = route.polyline.boundingMapRect
self.mapkitView.setRegion(MKCoordinateRegionForMapRect(rekt), animated: true)
})
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.cyan
renderer.alpha = 0.7
renderer.lineWidth = 7.0
return renderer
}
}
You should check if sourceCoordinates is nil.
e.g.
guard let sourceCoordinates = locationManager.location?.coordinate else {
return
}

UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger

I am trying to create a seat map layout functionality that takes the coordinates and create a map i want to provide the value of the sections that the map contains. I am using custom collectionViewLayout to create the cells but i am getting that error in the title .
Here is my protocol-
protocol SeatMapDelegate: class {
func getSectionCoordinates() -> [Int]
}
Definition -
func getSectionCoordinates() -> [Int] {
return sectionHeader
}
and then i am assigning the values to the array
var sectionHeader = [Int]()
sectionHeader=(delegate?.getSectionCoordinates())!
below code is my project for search and find coordinate on the map:
Maybe help you
// ViewController.swift
// MapKit Starter
//
// Created by Ehsan Amiri on 10/25/16.
// Copyright © 2016 Ehsan Amiri. All rights reserved.
//
import UIKit
import MapKit
import Foundation
class ViewController: UIViewController {
#IBOutlet var mapView: MKMapView?
#IBOutlet weak var text: UITextField!
var index = 0
var indexx = 0
let locationManager = CLLocationManager()
var picName:String?
var place :MKAnnotation?
var places = [Place]()
var place1 :MKAnnotation?
var places1 = [Place]()
override func viewDidLoad() {
super.viewDidLoad()
//downpic()
self.requestLocationAccess()
}
override func viewWillAppear(_ animated: Bool) {
let defaults = UserDefaults.standard
let age = defaults.integer(forKey: "maptype")
switch (age) {
case 0:
mapView?.mapType = .standard
case 1:
mapView?.mapType = .satellite
case 2:
mapView?.mapType = .hybrid
default:
mapView?.mapType = .standard
}
}
#IBAction func info(_ sender: Any) {
}
override var prefersStatusBarHidden: Bool {
return true
}
func requestLocationAccess() {
let status = CLLocationManager.authorizationStatus()
switch status {
case .authorizedAlways, .authorizedWhenInUse:
return
case .denied, .restricted:
print("location access denied")
default:
locationManager.requestWhenInUseAuthorization()
}
}
#IBAction func textField(_ sender: Any) {
mapView?.removeOverlays((mapView?.overlays)!)
mapView?.removeAnnotations((mapView?.annotations)!)
self.server()
_ = Timer.scheduledTimer(timeInterval: 10.0, target: self, selector: #selector(self.server), userInfo: nil, repeats: true)
let when = DispatchTime.now() + 1.5
DispatchQueue.main.asyncAfter(deadline: when) {
if self.indexx != 0 {
self.addAnnotations()
self.addPolyline()
}
}
}
#objc func server() {
place = nil
places = [Place]()
place1 = nil
places1 = [Place]()
indexx = 0
let id = text.text
print("id=\(id!)")
let url = URL(string: "my server")!
var request = URLRequest(url: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let postString = "id=\(id!)"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else { // check for fundamental networking error
print("error=\(String(describing: error))")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(String(describing: response))")
}
let responseString = String(data: data, encoding: .utf8)
print("responseString = \(String(describing: responseString))")
let stringgg = "notFound\n\n\n\n"
if responseString == stringgg {
print(stringgg)
}else{
let json = try! JSONSerialization.jsonObject(with: data, options: [])
let betterJSON = json as! NSArray
let jsonCount = betterJSON.count
print(betterJSON)
for item in betterJSON {
self.indexx += 1
let dictionary = item as? [String : Any]
let title = dictionary?["title"] as? String
let subtitle = dictionary?["description"] as? String
let latitude = dictionary?["latitude"] as? Double ?? 0, longitude = dictionary?["longitude"] as? Double ?? 0
self.place = Place(title: title, subtitle: subtitle, coordinate: CLLocationCoordinate2DMake(latitude , longitude ))
self.places.append(self.place as! Place)
print("latttt",longitude)
if self.indexx == 1{
let shipid = UserDefaults.standard
shipid.set(title, forKey: "origin")
shipid.set(subtitle, forKey: "date")
}
if jsonCount == self.indexx{
let shipid = UserDefaults.standard
shipid.set(title, forKey: "location")
self.place1 = Place(title: title, subtitle: subtitle, coordinate: CLLocationCoordinate2DMake(latitude , longitude ))
self.places1.append(self.place1 as! Place)
}
}
}
}
task.resume()
let when = DispatchTime.now() + 1.5
DispatchQueue.main.asyncAfter(deadline: when) {
if self.indexx != 0 {
self.addAnnotations()
self.addPolyline()
}
}
}
func addAnnotations() {
print("hhhh",places)
mapView?.delegate = self
mapView?.removeAnnotations((mapView?.annotations)!)
mapView?.addAnnotations(places1)
let overlays = places1.map { MKCircle(center: $0.coordinate, radius: 100) }
mapView?.addOverlays(overlays)
}
func addPolyline() {
var locations = places.map { $0.coordinate }
let polyline = MKPolyline(coordinates: &locations, count: locations.count)
// print("Number of locations: \(locations.count)")
index = locations.capacity
mapView?.add(polyline)
}
}
extension ViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
else {
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "annotationView") ?? MKAnnotationView()
annotationView.image = UIImage(named:"place icon")
annotationView.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
annotationView.canShowCallout = true
return annotationView
}
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if overlay is MKCircle {
let renderer = MKCircleRenderer(overlay: overlay)
renderer.fillColor = UIColor.black.withAlphaComponent(0.5)
renderer.strokeColor = UIColor.blue
renderer.lineWidth = 2
return renderer
} else if overlay is MKPolyline {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.orange
renderer.lineWidth = 2
return renderer
}
return MKOverlayRenderer()
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
//guard let annotation = view.annotation as? Place, let title = annotation.title else { return }
let shipidname = text.text
let shipid = UserDefaults.standard
shipid.set(shipidname, forKey: "shipid")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let secondViewController = storyboard.instantiateViewController(withIdentifier: "shipinfo")
self.present(secondViewController, animated: true, completion: nil)
}
}

MapKit Direction to Selected annotation

Trying to get direction to selected annotation on the map from the current location of the User but not sure how to catch selected annotation(when user selecting one of them) and show direction.Checked different topics on the Stack but there is not a lot of fresh information about how catch selected annotation and show direction for user location.Please advise.
import UIKit
import MapKit
import CoreLocation
class NavigationVC: UIViewController {
#IBOutlet weak var mapView: MKMapView!
let manager = CLLocationManager()
let request = MKLocalSearchRequest()
override func viewDidLoad() {
super.viewDidLoad()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
}
}
//MARK: CONFIGURATION OF MAPVIEW
extension NavigationVC: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations
locations: [CLLocation]) {
let location = locations[0]
let span: MKCoordinateSpan = MKCoordinateSpanMake(0.1, 0.1 )
let userLocation:CLLocationCoordinate2D =
CLLocationCoordinate2DMake(location.coordinate.latitude,
location.coordinate.longitude)
let region: MKCoordinateRegion =
MKCoordinateRegionMake(userLocation, span)
mapView.setRegion(region, animated: true)
self.mapView.showsUserLocation = true
request.naturalLanguageQuery = "Currency exchange"
request.region = mapView.region
let activeSearch = MKLocalSearch(request: request)
activeSearch.start { (response, error) in
guard let response = response else {
return
}
for item in response.mapItems {
let annotation = MKPointAnnotation()
annotation.coordinate = item.placemark.coordinate
annotation.title = item.name
DispatchQueue.main.async {
self.mapView.addAnnotation(annotation)
}
}
}
}
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) ->
MKOverlayRenderer {
let polylineRenderer = MKPolylineRenderer(overlay: overlay)
polylineRenderer.strokeColor = UIColor.blue
polylineRenderer.fillColor = UIColor.red
polylineRenderer.lineWidth = 2
return polylineRenderer
}
}
To get the path on the map from your position to the annotation follow this code:
annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2D(latitude: CLLocationDegrees(lat),longitude: CLLocationDegrees(lon))
self.map?.addAnnotation(annotation)
var route : MKRoute? = nil
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
let directionRequest = MKDirectionsRequest()
directionRequest.source = MKMapItem.forCurrentLocation();
directionRequest.destination = MKMapItem(placemark: MKPlacemark(coordinate:(self?.annotation.coordinate)!))
directionRequest.transportType = .automobile
let directions = MKDirections(request: directionRequest)
directions.calculate {
(response, error) -> Void in
guard let response = response else {
if let error = error {
print("Error: \(error)")
}
return
}
route = response.routes[0]
if let percorso = route{
DispatchQueue.main.async { [weak self] in
self?.map?.add((percorso.polyline), level: MKOverlayLevel.aboveRoads)
}
}
}
}
You have only to select the correct annotation, maybe try to register a touch listener on the annotation.
Use didSelect delegate method.
e.g.
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
guard let annotation = view.annotation else {
return
}
let directionRequest = MKDirectionsRequest()
directionRequest.source = MKMapItem.forCurrentLocation()
directionRequest.destination = MKMapItem(placemark: MKPlacemark(coordinate: annotation.coordinate))
directionRequest.transportType = .automobile
let directions = MKDirections(request: directionRequest)
directions.calculate {
(response, error) -> Void in
guard let response = response else {
if let error = error {
print("Error: \(error)")
}
return
}
if !response.routes.isEmpty {
let route = response.routes[0]
DispatchQueue.main.async { [weak self] in
self?.mapView.add(route.polyline)
}
}
}
}
Don't forget guard to prevent crash.
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) ->
MKOverlayRenderer {
guard overlay is MKPolyline else {
return MKPolylineRenderer()
}
...
}
Good luck!

How to display different color in annotation point in map?

Can't display color of annotation point in map , how it could be solved here's my code .i declared even function of color in MKPointAnnotation even i can't change the color , is there i have missed any codes ??
class NearbyViewController: UIViewController,MKMapViewDelegate,CLLocationManagerDelegate {
#IBOutlet weak var mapview: MKMapView!
#IBOutlet weak var name: UILabel!
var locationManager : CLLocationManager!
#IBOutlet weak var menu: UIBarButtonItem!
var schoolMap : [schools] = []
var collegeMap : [Colleges] = []
var universityMap : [University] = []
class MyPointAnnotation : MKPointAnnotation {
var pinTintColor: UIColor?
}
override func viewDidLoad() {
super.viewDidLoad()
getschoolMapJson()
getcollegeMapJson()
getuniversityMapJson()
menu.target = self.revealViewController()
menu.action = #selector(SWRevealViewController.revealToggle(_:))
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.distanceFilter = 1.00
locationManager.startUpdatingLocation()
}
override func viewWillAppear(_ animated: Bool) {
mapview.reloadInputViews()
}
override func viewDidAppear(_ animated: Bool) {
mapview.reloadInputViews()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
let location = locations[0]
let span = MKCoordinateSpanMake(0.05, 0.05)
let mylocation = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let region = MKCoordinateRegionMake(mylocation, span)
mapview.setRegion(region, animated: true)
self.mapview.showsUserLocation = true
}
func getschoolMapJson(){
if (schoolMap.count > 0){
return
}
let url = NSURL(string: "http://www.myeducationhunt.com/api/v1/schools")
var request = URLRequest(url: url! as URL)
request.httpMethod = "GET"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
Alamofire.request(request).responseJSON(){ response in
switch response.result{
case.success(let data):
print("success api",data)
let myresponse = JSON(data)
/*for i in 0..<self.myresponse.count{
let schools_data = schools(schoolJson:self.myresponse[i])
self.schooldata.append(schools_data)
}*/
for school in myresponse.array!{
let schoolsObj = schools(schoolJson: school)
//Add Pin
let location = CLLocationCoordinate2DMake((schoolsObj.latitude) , (schoolsObj.longitude))
let span = MKCoordinateSpanMake(10.0, 10.0)
let region = MKCoordinateRegionMake(location, span)
self.mapview.setRegion(region, animated: true)
let annotation = MKPointAnnotation()
annotation.coordinate = location
annotation.title = schoolsObj.name
let pincolor = MyPointAnnotation()
pincolor.pinTintColor = .blue
// MKPinAnnotationColor.green
// let pinC = MKPinAnnotationView.greenPinColor()
// self.mapview.addAnnotation(pinC as! MKAnnotation)
self.mapview.addAnnotation(annotation)
self.schoolMap.append(schoolsObj)
}
// self.mapview.reloadInputViews()
case.failure(let error):
print("Not Success",error)
}
}
}
func getcollegeMapJson(){
if (collegeMap.count > 0){
return
}
let url = NSURL(string: "http://www.myeducationhunt.com/api/v1/colleges")
var request = URLRequest(url: url! as URL)
request.httpMethod = "GET"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
Alamofire.request(request).responseJSON(){ response in
switch response.result{
case.success(let data):
print("success api",data)
let myresponse = JSON(data)
/*for i in 0..<self.myresponse.count{
let schools_data = schools(schoolJson:self.myresponse[i])
self.schooldata.append(schools_data)
}*/
for college in myresponse.array!{
let collegeObj = Colleges(collegeJson: college)
//Add Pin
let location = CLLocationCoordinate2DMake((collegeObj.latitude) , (collegeObj.longitude))
let span = MKCoordinateSpanMake(10.0, 10.0)
let region = MKCoordinateRegionMake(location, span)
self.mapview.setRegion(region, animated: true)
let annotation = MKPointAnnotation()
annotation.coordinate = location
annotation.title = collegeObj.name
self.mapview.addAnnotation(annotation)
self.collegeMap.append(collegeObj)
}
case.failure(let error):
print("Not Success",error)
}
}
}
func getuniversityMapJson(){
if (universityMap.count > 0){
return
}
let url = NSURL(string: "http://www.myeducationhunt.com/api/v1/universities")
var request = URLRequest(url: url! as URL)
request.httpMethod = "GET"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
Alamofire.request(request).responseJSON(){ response in
switch response.result{
case.success(let data):
print("success api",data)
let myresponse = JSON(data)
for university in myresponse.array!{
let universityObj = University(universityJson: university)
//Add Pin
let location = CLLocationCoordinate2DMake((universityObj.latitude) , (universityObj.longitude))
let span = MKCoordinateSpanMake(10.0, 10.0)
let region = MKCoordinateRegionMake(location, span)
self.mapview.setRegion(region, animated: true)
let annotation = MKPointAnnotation()
annotation.coordinate = location
annotation.title = universityObj.name
self.mapview.addAnnotation(annotation)
self.universityMap.append(universityObj)
}
case.failure(let error):
print("Not Success",error)
}
}
}
}
I am confused to display annotation point color i tried in many ways
but can't do it .
You have to add the following function. I hope this will solve your issue.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "myAnnotation") as? MKPinAnnotationView
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "myAnnotation")
} else {
annotationView?.annotation = annotation
}
if let annotation = annotation as? MyPointAnnotation {
annotationView?.pinTintColor = annotation.pinTintColor
}
return annotationView
}

Resources