I am trying to open automatically the Maps App with Navigation, when pressing a Button.
My ViewController look like this:
import UIKit
import MapKit
class WhereViewController: UIViewController {
#IBOutlet weak var MapView: MKMapView!
#IBAction func navigateButtonHandler(_ sender: UIButton) {
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView,
calloutAccessoryControlTapped control: UIControl) {
let location = view.annotation as! Artwork
let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving]
location.mapItem().openInMaps(launchOptions: launchOptions)
}
}
override func viewDidLoad() {
super.viewDidLoad()
// set initial location in Honolulu
let initialLocation = CLLocation(latitude: 21.282778, longitude: -157.829444)
centerMapOnLocation(location: initialLocation)
//MapView.delegate = self
// show artwork on map
let artwork = Artwork(title: "King David Kalakaua",
locationName: "Waikiki Gateway Park",
discipline: "Sculpture",
coordinate: CLLocationCoordinate2D(latitude: 21.283921, longitude: -157.831661))
MapView.addAnnotation(artwork)
}
let regionRadius: CLLocationDistance = 1000
func centerMapOnLocation(location: CLLocation) {
let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate,
regionRadius, regionRadius)
MapView.setRegion(coordinateRegion, animated: true)
}
}
And my Artwork Swift File looks like this:
import Foundation
import MapKit
import Contacts
class Artwork: NSObject, MKAnnotation {
let title: String?
let locationName: String
let discipline: String
let coordinate: CLLocationCoordinate2D
init(title: String, locationName: String, discipline: String, coordinate: CLLocationCoordinate2D) {
self.title = title
self.locationName = locationName
self.discipline = discipline
self.coordinate = coordinate
super.init()
}
var subtitle: String? {
return locationName
}
// Annotation right callout accessory opens this mapItem in Maps app
func mapItem() -> MKMapItem {
let addressDict = [CNPostalAddressStreetKey: subtitle!]
let placemark = MKPlacemark(coordinate: coordinate, addressDictionary: addressDict)
let mapItem = MKMapItem(placemark: placemark)
mapItem.name = title
return mapItem
}
}
When i press the button, is doesn't work. Where is my mistake?
Hope you can help me.
I follow these Tutorial for the MapKit:
https://www.raywenderlich.com/548-mapkit-tutorial-getting-started
Thanks for your answer
Related
I would like to add a custom image for a callout annotation via a subclass (previous questions did not include using a subclass)
Here is my code thus far:
Subclass named "Capital.swift"
import MapKit
import UIKit
class Capital: NSObject, MKAnnotation {
var title: String?
var coordinate: CLLocationCoordinate2D
var info: String
// here we would add the custom image
init(title: String, coordinate: CLLocationCoordinate2D, info: String) {
self.title = title
self.coordinate = coordinate
self.info = info
// add additional lines as needed
}
}
Here is my code for the ViewController.swift
import MapKit
import UIKit
class ViewController: UIViewController, MKMapViewDelegate {
#IBOutlet var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
let london = Capital(title: "London", coordinate: CLLocationCoordinate2D(latitude: 51.507222, longitude: -0.1275), info: "Home to the 2012 Summer Olympics.")
let oslo = Capital(title: "Oslo", coordinate: CLLocationCoordinate2D(latitude: 59.95, longitude: 10.75), info: "Founded over a thousand years ago.")
let paris = Capital(title: "Paris", coordinate: CLLocationCoordinate2D(latitude: 48.8567, longitude: 2.3508), info: "Often called the City of Light.")
let rome = Capital(title: "Rome", coordinate: CLLocationCoordinate2D(latitude: 41.9, longitude: 12.5), info: "Has a whole country inside it.")
let washington = Capital(title: "Washington DC", coordinate: CLLocationCoordinate2D(latitude: 38.895111, longitude: -77.036667), info: "Named after George himself.")
mapView.addAnnotations([london, oslo, paris, rome, washington])
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "Capital"
if annotation is Capital {
if let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) {
annotationView.annotation = annotation
return annotationView
} else {
let annotationView = MKPinAnnotationView(annotation:annotation, reuseIdentifier:identifier)
annotationView.isEnabled = true
annotationView.canShowCallout = true
let btn = UIButton(type: .detailDisclosure)
annotationView.rightCalloutAccessoryView = btn
return annotationView
}
}
return nil
}
Here we add the custom image to the annotationView
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
let capital = view.annotation as! Capital
let placeName = capital.title
let placeInfo = capital.info
// Add custom image
// Add Segue
performSegue(withIdentifier: "segue1", sender: (capital.title, capital.coordinate, capital.info))
}
}
Thanks
I would like to add a custom image for a callout annotation via a subclass (previous questions did not include using a subclass)
Here is my code thus far:
Subclass named "Capital.swift"
import MapKit
import UIKit
class Capital: NSObject, MKAnnotation {
var title: String?
var coordinate: CLLocationCoordinate2D
var info: String
// here we would add the custom image
init(title: String, coordinate: CLLocationCoordinate2D, info: String) {
self.title = title
self.coordinate = coordinate
self.info = info
// add additional lines as needed
}
}
Here is my code for the ViewController.swift
import MapKit
import UIKit
class ViewController: UIViewController, MKMapViewDelegate {
#IBOutlet var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
let london = Capital(title: "London", coordinate: CLLocationCoordinate2D(latitude: 51.507222, longitude: -0.1275), info: "Home to the 2012 Summer Olympics.")
let oslo = Capital(title: "Oslo", coordinate: CLLocationCoordinate2D(latitude: 59.95, longitude: 10.75), info: "Founded over a thousand years ago.")
let paris = Capital(title: "Paris", coordinate: CLLocationCoordinate2D(latitude: 48.8567, longitude: 2.3508), info: "Often called the City of Light.")
let rome = Capital(title: "Rome", coordinate: CLLocationCoordinate2D(latitude: 41.9, longitude: 12.5), info: "Has a whole country inside it.")
let washington = Capital(title: "Washington DC", coordinate: CLLocationCoordinate2D(latitude: 38.895111, longitude: -77.036667), info: "Named after George himself.")
mapView.addAnnotations([london, oslo, paris, rome, washington])
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "Capital"
if annotation is Capital {
if let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) {
annotationView.annotation = annotation
return annotationView
} else {
let annotationView = MKPinAnnotationView(annotation:annotation, reuseIdentifier:identifier)
annotationView.isEnabled = true
annotationView.canShowCallout = true
let btn = UIButton(type: .detailDisclosure)
annotationView.rightCalloutAccessoryView = btn
return annotationView
}
}
return nil
}
Here we add the custom image to the annotationView
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
let capital = view.annotation as! Capital
let placeName = capital.title
let placeInfo = capital.info
// Add custom image
let SecondViewController = self.storyboard?.instantiateViewController(withIdentifier: "SecondViewController")
self.show(SecondViewController!, sender: nil)
}
}
Thanks
The map view's delegate, not the annotation object itself, decides the annotation view for an annotation. So you need to set the image in your implementation of the map view delegate method:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?
If you want, your Capitol class could vend the correct image, for example:
class Capital: NSObject, MKAnnotation {
var title: String?
var coordinate: CLLocationCoordinate2D
var info: String
var imageForAnnotationView: UIImage? {
guard let title = title else { return nil }
return UIImage(named: "\(title).jpg")
}
…
You could rewrite your delegate implementation and obtain the image like so:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "Capital"
guard let annotation = annotation as? Capital else { return nil }
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) ?? MKPinAnnotationView(annotation:annotation, reuseIdentifier:identifier)
annotationView.annotation = annotation
annotationView.isEnabled = true
annotationView.canShowCallout = true
annotationView.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
// set the image to the annotation view
annotationView.image = annotation.imageForAnnotationView
return annotationView
}
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))
I am using the MapKit and I am receiving the following error:
The locations.count? is not working even when I am putting that in as the argument. It says that it doesn't allow Int as a parameter. I'm not too sure why this isn't working.
import UIKit
import MapKit
class MapViewController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var myMapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
let italy = MKPointAnnotation()
italy.coordinate = CLLocationCoordinate2D(latitude: 41.8947400, longitude: 12.4839000)
italy.title = "Rome, Italy"
let england = MKPointAnnotation()
england.coordinate = CLLocationCoordinate2D(latitude: 51.5085300, longitude: -0.1257400)
england.title = "London, England"
let norway = MKPointAnnotation()
norway.coordinate = CLLocationCoordinate2D(latitude: 59.914225, longitude: 10.75256)
norway.title = "Oslo, Norway"
let spain = MKPointAnnotation()
spain.coordinate = CLLocationCoordinate2D(latitude: 40.41694, longitude: -3.70081)
spain.title = "Madrid, Spain"
let locations = [italy, england, norway, spain]
myMapView.addAnnotation(locations)
}
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
let pin = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "pinIdentifier")
pin.canShowCallout = true
return pin
}
}
It should be:
myMapView.addAnnotations(locations) //note the "s"
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