How do I create a line (polyline) between location points in Swift? - ios

I am trying to make an app that tracks a user's location and creates a line following where the user went. I have created a bunch of annotations following where the user went, but can't figure out how to create a line between them. I am new to swift and Xcode and I have looked all over the internet but can't find anything that works. Picture of app with annotations following user location
Here is my code:
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
#IBOutlet var mapView: MKMapView?
//Map
#IBOutlet weak var map: MKMapView!
#IBOutlet weak var lblSpeed: UILabel!
let manager = CLLocationManager()
#IBOutlet weak var lblAltitude: UILabel!
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
let span:MKCoordinateSpan = MKCoordinateSpanMake(0.01, 0.01)
let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
let region:MKCoordinateRegion = MKCoordinateRegionMake(myLocation, span)
lblAltitude.text = String(format:"%.2f", location.altitude)
lblSpeed.text = String(format:"%.2f", location.speed)
self.map.showsUserLocation = true
var testLocation = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
var annotation = MKPointAnnotation()
annotation.coordinate = testLocation
map.addAnnotation(annotation)
var locationTest = [CLLocation(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)]
var coordinates = locations.map({(location: CLLocation!) -> CLLocationCoordinate2D in return location.coordinate})
var polyline = MKPolyline(coordinates: &testLocation, count: locations.count)
func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
if overlay is MKPolyline {
let polylineRenderer = MKPolylineRenderer(overlay: overlay)
polylineRenderer.strokeColor = UIColor.blue
polylineRenderer.lineWidth = 5
return polylineRenderer
}
return nil
}
}

You can try
let blueLocation1 = CLLocationCoordinate2D(latitude: lat1, longitude: lon1)
let blueLocation2 = CLLocationCoordinate2D(latitude: lat2, longitude: lon2)
let routeLine = MKPolyline(coordinates:[blueLocation1,blueLocation2], count:2)
self.mapView.add(routeLine)
// Also you may be keen to zoom out to show all annotations + seeing drawn line
func zoomToFitMapAnnotations(aMapView:MKMapView)
{
if(aMapView.annotations.count == 0)
{
return
}
var topLeftCoord = CLLocationCoordinate2D.init(latitude: -90, longitude: 180)
var bottomRightCoord = CLLocationCoordinate2D.init(latitude: 90, longitude: -180)
for i in 0..<aMapView.annotations.count
{
let annotation = aMapView.annotations[i]
topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude);
topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude);
bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude);
bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude);
}
let resd = CLLocationCoordinate2D.init(latitude: topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5, longitude: topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5)
let span = MKCoordinateSpan.init(latitudeDelta: fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.3, longitudeDelta: fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.3)
var region = MKCoordinateRegion.init(center: resd, span: span);
region = aMapView.regionThatFits(region)
aMapView.setRegion(region, animated: true)
}
// Also rendererForOverlay func must be in class level not inside another func
func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
if overlay is MKPolyline {
let polylineRenderer = MKPolylineRenderer(overlay: overlay)
polylineRenderer.strokeColor = UIColor.blue
polylineRenderer.lineWidth = 5
return polylineRenderer
}
return nil
}

Related

Highlight between two points on MapKit swift 5

I am struggling to try and Highlight the road between 2 points using MapKit. All I don't want directions i just want to try and Highlight the road between these two points.
My code is:
import UIKit
import MapKit
class ViewController: UIViewController {
#IBOutlet weak var mapView: MKMapView!
struct Points {
var name: String
var lattitude: CLLocationDegrees
var longtitude: CLLocationDegrees
}
override func viewDidLoad() {
super.viewDidLoad()
let points = [
Points(name: "Point 1", lattitude: 52.100525, longtitude: -9.623071),
Points(name: "Point 2", lattitude: 52.07241, longtitude: -9.575299)
]
fetchPointsOnMap(points)
}
func fetchPointsOnMap(_ points: [Points]) {
for points in points {
let annotations = MKPointAnnotation()
annotations.title = points.name
annotations.coordinate = CLLocationCoordinate2D(latitude:
points.lattitude, longitude: points.longtitude)
mapView.addAnnotation(annotations)
}
}
}`
You can draw a line:
directionsRequest.transportType = MKDirectionsTransportType.automobile
//Draw polyline by using MKRoute so it follows the street roads...
for (k, item) in arrayarrayPlacemarks.enumerated() {
if k < (arrayarrayPlacemarks.count - 1) {
directionsRequest.source = item
directionsRequest.destination = arrayarrayPlacemarks[k+1]
let directions = MKDirections(request: directionsRequest)
directions.calculate { (response:MKDirections.Response!, error: Error!) -> Void in
if error == nil {
self.locRoute = response.routes[0] as? MKRoute
let geodesic:MKPolyline = self.locRoute!.polyline
self.mapView.addOverlay(geodesic)
}
}
}
}
Delegate:
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if overlay.isKind(of: MKPolyline.self){
var polylineRenderer = MKPolylineRenderer(overlay: overlay)
polylineRenderer.fillColor = UIColor.blue
polylineRenderer.strokeColor = UIColor.blue
polylineRenderer.lineWidth = 2
return polylineRenderer
}
return MKOverlayRenderer(overlay: overlay)
}

How to draw circle overlay on MapKit that surrounds several annotations/coordinates?

I have an array [CLLocationCoordinate2D], I would like to draw a circle on MKMapView surrounding all these coordinates.
I have managed to draw a circle around a single CLLocationCoordinate2D as such:
let coordinate = CLLocationCoordinate2D(latitude: 53, longitude: 27)
self.mapView.add(MKCircle(center: coordinate, radius: 100))
extension MapViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
guard overlay is MKCircle else { return MKOverlayRenderer() }
let circle = MKCircleRenderer(overlay: overlay)
circle.strokeColor = UIColor.red
circle.fillColor = UIColor(red: 255, green: 0, blue: 0, alpha: 0.1)
circle.lineWidth = 1
return circle
}
}
How can I draw a circle that surrounds/encompasses all coordinates?, like below:
I came up with MKCoordinateRegion initializer, which provides the region of the coordinates, the extension has a computed property to provide the radius of the region.
extension MKCoordinateRegion {
init?(from coordinates: [CLLocationCoordinate2D]) {
guard coordinates.count > 1 else { return nil }
let a = MKCoordinateRegion.region(coordinates, fix: { $0 }, fix2: { $0 })
let b = MKCoordinateRegion.region(coordinates, fix: MKCoordinateRegion.fixMeridianNegativeLongitude, fix2: MKCoordinateRegion.fixMeridian180thLongitude)
guard (a != nil || b != nil) else { return nil }
guard (a != nil && b != nil) else {
self = a ?? b!
return
}
self = [a!, b!].min(by: { $0.span.longitudeDelta < $1.span.longitudeDelta }) ?? a!
}
var radius: CLLocationDistance {
let furthest = CLLocation(latitude: self.center.latitude + (span.latitudeDelta / 2),
longitude: center.longitude + (span.longitudeDelta / 2))
return CLLocation(latitude: center.latitude, longitude: center.longitude).distance(from: furthest)
}
// MARK: - Private
private static func region(_ coordinates: [CLLocationCoordinate2D],
fix: (CLLocationCoordinate2D) -> CLLocationCoordinate2D,
fix2: (CLLocationCoordinate2D) -> CLLocationCoordinate2D) -> MKCoordinateRegion? {
let t = coordinates.map(fix)
let min = CLLocationCoordinate2D(latitude: t.min { $0.latitude < $1.latitude }!.latitude,
longitude: t.min { $0.longitude < $1.longitude }!.longitude)
let max = CLLocationCoordinate2D(latitude: t.max { $0.latitude < $1.latitude }!.latitude,
longitude: t.max { $0.longitude < $1.longitude }!.longitude)
// find span
let span = MKCoordinateSpanMake(max.latitude - min.latitude, max.longitude - min.longitude)
// find center
let center = CLLocationCoordinate2D(latitude: max.latitude - span.latitudeDelta / 2,
longitude: max.longitude - span.longitudeDelta / 2)
return MKCoordinateRegion(center: fix2(center), span: span)
}
private static func fixMeridianNegativeLongitude(coordinate: CLLocationCoordinate2D) -> CLLocationCoordinate2D {
guard (coordinate.longitude < 0) else { return coordinate }
let fixedLng = 360 + coordinate.longitude
return CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: fixedLng)
}
private static func fixMeridian180thLongitude(coordinate: CLLocationCoordinate2D) -> CLLocationCoordinate2D {
guard (coordinate.longitude > 180) else { return coordinate }
let fixedLng = -360 + coordinate.longitude
return CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: fixedLng)
}
}
Usage:
let coordinates: [CLLocationCoordinate2D] = self.mapView.annotations.map{ $0.coordinate }
if let region = MKCoordinateRegion(from: coordinates) {
self.mapView.add(MKCircle(center: region.center, radius: region.radius))
}
Result is exactly what I want, with ability to handle coordinates crossing 180th meridian:

Value of type 'MKDirectionsRequest' has no member 'setSource'

For the practice of MapKit in iOS using Swift 2.0 targeted version iOS 8.0 drawing path between two points I am getting errors in my code that you can see above.
Here is my practice code:
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet var map: MKMapView!
var geocoder:CLGeocoder = CLGeocoder()
var location:CLLocation = CLLocation(latitude: 38, longitude: -77)
var next:CLLocation = CLLocation(latitude: 38.21, longitude: -77.21)
var locMark:MKPlacemark?
var destMark:MKPlacemark?
var manager:CLLocationManager = CLLocationManager()
var source:MKMapItem?
var destination:MKMapItem?
var request:MKDirectionsRequest = MKDirectionsRequest()
var directions:MKDirections = MKDirections()
var directionsResponse:MKDirectionsResponse = MKDirectionsResponse()
var route:MKRoute = MKRoute()
override func viewDidLoad() {
super.viewDidLoad()
manager.requestAlwaysAuthorization()
map.mapType = MKMapType.Satellite
locMark = MKPlacemark(coordinate: CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude), addressDictionary: nil)
destMark = MKPlacemark(coordinate: CLLocationCoordinate2DMake(next.coordinate.latitude, next.coordinate.longitude), addressDictionary: nil)
source = MKMapItem(placemark: locMark)
destination = MKMapItem(placemark: destMark)
request.setSource(source)
request.setDestination(destination)
request.transportType = MKDirectionsTransportType.Automobile
request.requestsAlternateRoutes = true
directions = MKDirections(request: request)
directions.calculateDirectionsWithCompletionHandler { (response:MKDirectionsResponse?, error:NSError?) -> Void in
if error == nil {
self.directionsResponse = response!
self.route = self.directionsResponse.routes[0] as! MKRoute
map.addOverlay(route.polyline, level: MKOverlayLevel.AboveRoads)
} else {
println(error)
}
}
}
func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
println("redenrerForOverlay")
if(overlay.isKindOfClass(MKPolyline)) {
var renderer: MKPolylineRenderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = Colors.psnGreen
renderer.lineWidth = 5
return renderer
}
return nil
}
func mapView(mapView: MKMapView!, viewForOverlay overlay: MKOverlay!) -> MKOverlayView! {
println("ViewForOverlay")
if (overlay.isKindOfClass(MKPolyline)) {
var lineView: MKPolylineView = MKPolylineView(overlay: overlay)
lineView.backgroundColor = Colors.psnGreen
return lineView;
}
return nil;
}
}
Zeeshan you just need to delete those two lines and add the two lines from Mark Answer , this below code is working fine:
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet var map: MKMapView!
var geocoder:CLGeocoder = CLGeocoder()
var location:CLLocation = CLLocation(latitude: 38, longitude: -77)
var next:CLLocation = CLLocation(latitude: 38.21, longitude: -77.21)
var locMark:MKPlacemark?
var destMark:MKPlacemark?
var manager:CLLocationManager = CLLocationManager()
var source:MKMapItem?
var destination:MKMapItem?
var request:MKDirectionsRequest = MKDirectionsRequest()
var directions:MKDirections = MKDirections()
var directionsResponse:MKDirectionsResponse = MKDirectionsResponse()
var route:MKRoute = MKRoute()
override func viewDidLoad() {
super.viewDidLoad()
manager.requestAlwaysAuthorization()
map.mapType = MKMapType.Satellite
locMark = MKPlacemark(coordinate: CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude), addressDictionary: nil)
destMark = MKPlacemark(coordinate: CLLocationCoordinate2DMake(next.coordinate.latitude, next.coordinate.longitude), addressDictionary: nil)
source = MKMapItem(placemark: locMark)
destination = MKMapItem(placemark: destMark)
request.source = source
request.destination = destination
request.transportType = MKDirectionsTransportType.Automobile
request.requestsAlternateRoutes = true
directions = MKDirections(request: request)
directions.calculateDirectionsWithCompletionHandler { (response:MKDirectionsResponse?, error:NSError?) -> Void in
if error == nil {
self.directionsResponse = response!
self.route = self.directionsResponse.routes[0] as! MKRoute
map.addOverlay(route.polyline, level: MKOverlayLevel.AboveRoads)
} else {
print(error)
}
}
}
func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
print("redenrerForOverlay")
if(overlay.isKindOfClass(MKPolyline)) {
var renderer: MKPolylineRenderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = Colors.psnGreen
renderer.lineWidth = 5
return renderer
}
return nil
}
func mapView(mapView: MKMapView!, viewForOverlay overlay: MKOverlay!) -> MKOverlayView! {
print("ViewForOverlay")
if (overlay.isKindOfClass(MKPolyline)) {
var lineView: MKPolylineView = MKPolylineView(overlay: overlay)
lineView.backgroundColor = Colors.psnGreen
return lineView;
}
return nil;
}
}
Try changing the two lines to this:
request.source = source
request.destination = destination
Swift uses the property directly, rather than an explicit setter (which is only available in Obj-C).

Annotations won't appear on MapView

I'm having trouble getting my annotations to display on my map view. Nothing is displaying right now. What is wrong with my code ?
Here is my base map view controller:
import UIKit
import MapKit
import CoreLocation
class MapViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
let goldenWordsYellow = UIColor(red: 247.00/255.0, green: 192.00/255.0, blue: 51.00/255.0, alpha: 0.5)
// Map View outlet declaration
#IBOutlet weak var mapView: MKMapView!
// Hamburger button declaration
#IBOutlet weak var menuButton:UIBarButtonItem!
var locationManager: CLLocationManager?
/* Really ugly code where I declare all of my static data */
let coordinatesARC = IssueLocation(locationName: "ARC", coordinate: CLLocationCoordinate2D(latitude: -76.49416565895079, longitude: 44.22928743712073))
let coordinatesJDUC = IssueLocation(locationName: "JDUC", coordinate: CLLocationCoordinate2D(latitude: -76.49507761001587, longitude: 44.22838027067406))
let coordinatesStaufferLibrary = IssueLocation(locationName: "Stauffer Library", coordinate: CLLocationCoordinate2D(latitude: -76.49615049362183, longitude: 44.228418710213944))
let coordinatesWalterLightHall = IssueLocation(locationName: "Walter Light Hall", coordinate: CLLocationCoordinate2D(latitude: -76.49166584014893, longitude: 44.22794205814507))
let coordinatesDupuisHall = IssueLocation(locationName: "Dupuis Hall", coordinate: CLLocationCoordinate2D(latitude: -76.4927065372467, longitude: 44.22867241054762))
let coordinatesHumphreyHall = IssueLocation(locationName: "Humphrey Hall", coordinate: CLLocationCoordinate2D(latitude: -76.49212718009949, longitude: 44.22688879714365))
let coordinatesBiosciencesComplex = IssueLocation(locationName: "Biosciences Complex", coordinate: CLLocationCoordinate2D(latitude: -76.49117231369019, longitude: 44.226327562781904))
let coordinatesBMH = IssueLocation(locationName: "Beamish-Munro Hall", coordinate: CLLocationCoordinate2D(latitude: -76.49271726608276, longitude: 44.228195760533175))
let coordinatesBotterellHall = IssueLocation(locationName: "Botterell Hall", coordinate: CLLocationCoordinate2D(latitude: -76.49160146713257, longitude: 44.22447468258034))
let coordinatesEtheringtonHall = IssueLocation(locationName: "Etherington Hall", coordinate: CLLocationCoordinate2D(latitude: -76.49390816688538, longitude: 44.224282471751785))
let coordinatesJefferyHall = IssueLocation(locationName: "Jeffery Hall", coordinate: CLLocationCoordinate2D(latitude: -76.49605393409729, longitude: 44.22590855555731))
let coordinatesEllisHall = IssueLocation(locationName: "Ellis Hall", coordinate: CLLocationCoordinate2D(latitude: -76.49602174758911, longitude: 44.22636984774898))
let coordinatesMackintoshCorryHall = IssueLocation(locationName: "Mackintosh-Corry Hall", coordinate: CLLocationCoordinate2D(latitude: -76.49697124958038, longitude: 44.22677731951135))
let coordinatesChernoffHall = IssueLocation(locationName: "Chernoff Hall", coordinate: CLLocationCoordinate2D(latitude: -76.49884343147278, longitude: 44.22436704459368))
let coordinatesLeggetHall = IssueLocation(locationName: "Legget Hall", coordinate: CLLocationCoordinate2D(latitude: -76.49749159812927, longitude: 44.22362126170883))
let coordinatesLeonardHall = IssueLocation(locationName: "Leonard Hall", coordinate: CLLocationCoordinate2D(latitude: -76.50065660476685, longitude: 44.22429016019697))
let coordinatesVictoriaHall = IssueLocation(locationName: "Victoria Hall", coordinate: CLLocationCoordinate2D(latitude: -76.49863958358765, longitude: 44.22550492192426))
let coordinatesStirlingHall = IssueLocation(locationName: "Stirling Hall", coordinate: CLLocationCoordinate2D(latitude: -76.49767398834229, longitude: 44.22463613919133))
let coordinatesWestCampus = IssueLocation(locationName: "West Campus", coordinate: CLLocationCoordinate2D(latitude: -76.51471138000487, longitude: 44.22438242146097))
override func viewDidLoad() {
super.viewDidLoad()
// Hamburger button configuration
if self.revealViewController() != nil {
menuButton.target = self.revealViewController()
menuButton.action = "revealToggle:"
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
// Setting the Map type to standard
mapView.mapType = MKMapType.Standard
// Configuring locationManager and mapView delegate
locationManager = CLLocationManager()
mapView.delegate = self
// Set the center of campus as the first location, before we show the actual user location
let initialLocation = CLLocationCoordinate2D(latitude: 44.226181, longitude: -76.495614)
let latitudeDelta:CLLocationDegrees = 0.015
let longitudeDelta:CLLocationDegrees = 0.015
let span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta)
let coordinateRegion = MKCoordinateRegionMake(initialLocation, span)
mapView.setRegion(coordinateRegion, animated: true)
let ARCAnnotation = MKPointAnnotation()
ARCAnnotation.title = coordinatesARC.locationName
ARCAnnotation.subtitle = coordinatesARC.locationName
ARCAnnotation.coordinate = coordinatesARC.coordinate
mapView.addAnnotation(ARCAnnotation)
// Adding all annotations to the map view
mapView.addAnnotation(coordinatesARC)
mapView.addAnnotation(coordinatesJDUC)
mapView.addAnnotation(coordinatesStaufferLibrary)
mapView.addAnnotation(coordinatesWalterLightHall)
mapView.addAnnotation(coordinatesDupuisHall)
mapView.addAnnotation(coordinatesHumphreyHall)
mapView.addAnnotation(coordinatesBiosciencesComplex)
mapView.addAnnotation(coordinatesBMH)
mapView.addAnnotation(coordinatesBotterellHall)
mapView.addAnnotation(coordinatesEtheringtonHall)
mapView.addAnnotation(coordinatesJefferyHall)
mapView.addAnnotation(coordinatesEllisHall)
mapView.addAnnotation(coordinatesMackintoshCorryHall)
mapView.addAnnotation(coordinatesChernoffHall)
mapView.addAnnotation(coordinatesLeggetHall)
mapView.addAnnotation(coordinatesLeonardHall)
mapView.addAnnotation(coordinatesVictoriaHall)
mapView.addAnnotation(coordinatesStirlingHall)
mapView.addAnnotation(coordinatesWestCampus)
mapView.showsUserLocation = true
locationManager?.startUpdatingLocation()
}
func mapView(mapView: MKMapView, didUpdateUserLocation userLocation: MKUserLocation) {
mapView.centerCoordinate = CLLocationCoordinate2D(latitude: 44.226181, longitude: -76.495614)
}
func checkLocationAuthorizationStatus() {
if CLLocationManager.authorizationStatus() == .AuthorizedWhenInUse {
mapView.showsUserLocation = true
} else {
locationManager?.requestWhenInUseAuthorization()
}
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
checkLocationAuthorizationStatus()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
Here is my map view controller extension:
import Foundation
import MapKit
extension MapViewController {
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if let annotation = annotation as? IssueLocation {
let identifier = "pin"
var view: MKPinAnnotationView
if let dequeuedView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) as? MKPinAnnotationView {
dequeuedView.annotation = annotation // NOTE: 2 options here for the "annotation" at the end of this line. I choose the first one but am in doubt.
view = dequeuedView
} else {
view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier) // NOTE: another unsure choice for the "annotation" right before the comma
view.canShowCallout = true
view.calloutOffset = CGPoint(x: -5, y: 5)
view.rightCalloutAccessoryView = UIButton(type: UIButtonType.DetailDisclosure) as UIView
}
return view
}
return nil
}
func mapView(mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
let location = view.annotation as! IssueLocation
let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeWalking]
location.mapItem().openInMapsWithLaunchOptions(launchOptions)
}
}
And here is my class:
import Foundation
import MapKit
import AddressBook
import Contacts
class IssueLocation: NSObject, MKAnnotation {
let locationName: String
let coordinate: CLLocationCoordinate2D
init(locationName: String, coordinate: CLLocationCoordinate2D) {
self.locationName = locationName
self.coordinate = coordinate
super.init()
}
var subtitle: String? {
return locationName
}
var title: String? {
return locationName
}
func mapItem() -> MKMapItem {
let addressDictionary = [String(CNPostalAddressStreetKey): locationName]
let placemark = MKPlacemark(coordinate: coordinate, addressDictionary: addressDictionary)
let mapItem = MKMapItem(placemark: placemark)
mapItem.name = locationName
return mapItem
This issue is with your coordinates.
Your code:
let coordinatesARC = IssueLocation(locationName: "ARC", coordinate: CLLocationCoordinate2D(latitude: -76.49416565895079, longitude: 44.22928743712073))
let coordinatesJDUC = IssueLocation(locationName: "JDUC", coordinate: CLLocationCoordinate2D(latitude: -76.49507761001587, longitude: 44.22838027067406))
Corrected code:
let coordinatesARC = IssueLocation(locationName: "ARC", coordinate: CLLocationCoordinate2D(latitude: 44.22928743712073, longitude: -76.49416565895079))
let coordinatesJDUC = IssueLocation(locationName: "JDUC", coordinate: CLLocationCoordinate2D(latitude: 44.22838027067406, longitude: -76.49507761001587))

How to add overlay path in MKMapView swift

I want to add a overlay path among multiple coordinates in mapview. I tried like below code, but it shows a error of "cannot invoke 'map' with an argument list of type ((CLLocation) -> CLLocationCoordinate2D)". Please let me know how can i fix this ?
My ViewController.swift file
import UIKit
import MapKit
class ViewController: UIViewController, MKMapViewDelegate{
#IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
//For Location 1
let location1 = CLLocationCoordinate2D(
latitude: 51.481188400000010000,
longitude: -0.190209099999947280
)
let annotation1 = MKPointAnnotation()
annotation1.coordinate = location1;
annotation1.title = "Chelsea"
annotation1.subtitle = "Chelsea"
let span = MKCoordinateSpanMake(0.15, 0.15)
let region1 = MKCoordinateRegion(center: location1, span: span)
mapView.setRegion(region1, animated: true)
mapView.addAnnotation(annotation1)
//For Location 2
let location2 = CLLocationCoordinate2D(
latitude: 51.554947700000010000,
longitude: -0.108558899999934510
)
let annotation2 = MKPointAnnotation()
annotation2.coordinate = location2;
annotation2.title = "Arsenal"
annotation2.subtitle = "Arsenal"
let region2 = MKCoordinateRegion(center: location1, span: span)
mapView.setRegion(region2, animated: true)
mapView.addAnnotation(annotation2)
var locations = [CLLocation(latitude: 51.481188400000010000, longitude: -0.190209099999947280), CLLocation(latitude: 51.554947700000010000,longitude: -0.108558899999934510)]
//This line shows error
var coordinates = locations.map({(location: CLLocation) -> CLLocationCoordinate2D in return location.coordinate})
var polyline = MKPolyline(coordinates: &coordinates, count: locations.count)
mapView.addOverlay(polyline)
}
func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
if overlay is MKPolyline {
var polylineRenderer = MKPolylineRenderer(overlay: overlay)
polylineRenderer.strokeColor = UIColor.blueColor()
polylineRenderer.lineWidth = 5
return polylineRenderer
}
return nil
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
This should work:
var coordinates = locations.map {
location in
return location.coordinate
}
One-liner:
var coordinates = locations.map { $0.coordinate }
The problem with your code was that locations is a variable of type [CLLocation!] (note the exclamation mark here), but you are declaring its elements as CLLocation (without the !) in the closure:
(location: CLLocation) -> CLLocationCoordinate2D

Resources