Custom User Location Annotation Callout doesn't work - swift

I want to change the standard annotation callout view for the user location annotation in Swift.
Therefore I created a custom XIB and a custom class. In the mapkit delegate I load the respective annotations. The custom annotations appear for every map annotation added as expected but not for the "current user location". Here the standard one is being displayed still. How do I need to change my code so the standard one will be exchanged to the one below?
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
var identifier = ""
if (annotation is MKUserLocation) {
identifier = "userLocation"
let annotationInfo:[String:AnyObject] = ["featureTypeId": GISFeatureType.AnnotationCurrentPosition.rawValue]
if let userAnnotation = MapAnnotation(annotationInfo: annotationInfo) {
userAnnotation.title = "Aktueller Standort"
let annotationView = MapAnnotationView(annotation: userAnnotation, reuseIdentifier: identifier)
annotationView.canShowCallout = true
return annotationView
}
}
// Annotation is not user location
guard let annotation = annotation as? MapAnnotation, let featureTypeId = annotation.featureTypeId else {
return nil
}
identifier = "MapAnnotation"
let annotationView = MapAnnotationView(annotation: annotation, reuseIdentifier: identifier)
switch (featureTypeId) {
case .AnnotationIncident:
identifier = "MapAnnotationIncidentDetailView"
let detailView = UIView.loadFromNibNamed(identifier) as! MapAnnotationIncidentDetailView
detailView.incident = annotation.incident
annotationView.detailCalloutAccessoryView = detailView
case .AnnotationAED:
identifier = "MapAnnotationAEDDetailView"
let detailView = UIView.loadFromNibNamed(identifier) as! MapAnnotationAEDDetailView
detailView.aed = annotation.aed
annotationView.detailCalloutAccessoryView = detailView
case .AnnotationCurrentPosition:
identifier = "MapAnnotationCurrentDetailView"
let detailView = UIView.loadFromNibNamed(identifier) as! MapAnnotationCurrentDetailView
annotationView.detailCalloutAccessoryView = detailView
default:
return nil
}
annotationView.canShowCallout = true
return annotationView
}

Related

Apple maps show customies pin details and alway open mode [duplicate]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am having some trouble getting a custom annotation to load inside of my map view when I try to place a pin.
import UIKit
import MapKit
import CoreLocation
class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate{
#IBAction func ReportBtn(sender: AnyObject) {
//MARK: Report Date And Time Details
let ReportTime = NSDate()
let TimeStamp = NSDateFormatter()
TimeStamp.timeStyle = NSDateFormatterStyle.ShortStyle
TimeStamp.dateStyle = NSDateFormatterStyle.ShortStyle
TimeStamp.stringFromDate(ReportTime)
//MARK: Default Point Annotation Begins
let ReportAnnotation = MKPointAnnotation()
ReportAnnotation.title = "Annotation Created"
ReportAnnotation.subtitle = ReportTime.description
ReportAnnotation.coordinate = locationManager.location!.coordinate
mapView(MainMap, viewForAnnotation: ReportAnnotation)
MainMap.addAnnotation(ReportAnnotation)
}
#IBOutlet weak var MainMap: MKMapView!
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.startUpdatingLocation()
self.MainMap.showsUserLocation = true
}
//MARK: - Location Delegate Methods
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last
let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02 ))
self.MainMap.setRegion(region, animated: true)
//self.locationManager.stopUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError){
print(error.localizedDescription)
}
//MARK:Custom Annotation Begins Here
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
guard !annotation.isKindOfClass(MKUserLocation) else {
return nil
}
/*if annotation.isKindOfClass(MKUserLocation){
//emty return, guard wasn't cooperating
}else{
return nil
}*/
let annotationIdentifier = "AnnotationIdentifier"
var annotationView: MKAnnotationView?
if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(annotationIdentifier){
annotationView = dequeuedAnnotationView
annotationView?.annotation = annotation
}
else{
let av = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
av.rightCalloutAccessoryView = UIButton(type: .DetailDisclosure)
annotationView = av
}
if let annotationView = annotationView {
annotationView.canShowCallout = true
annotationView.image = UIImage(named: "image.png")
}
return annotationView
}
}
Added Information
I am positive that the button functionality works perfect. With the current code, dumped above, the default red pin annotation appears right where it should. When I tap on the pin, the description I specified also appears without an issue. The only problem I am having with this code is that I cannot get my image to take the place of the boring, default red pin
I recommend subclassing `MKPointAnnotation.
Pokémon Pin
I have included only the necessary code to display a custom map pin. Think of it as a template.
Outline
We will create a point annotation object and assigning a custom image name with the CustomPointAnnotation class.
We will subclass the MKPointAnnotation to set image and assign it on the delegate protocol method viewForAnnotation.
We will add an annotation view to the map after setting the coordinate of the point annotation with a title and a subtitle.
We will implement the viewForAnnotation method which is an MKMapViewDelegate protocol method which gets called for pins to display on the map. viewForAnnotation protocol method is the best place to customise the pin view and assign a custom image to it.
We will dequeue and return a reusable annotation for the given identifier and cast the annotation to our custom CustomPointAnnotation class in order to access the image name of the pin.
We will create a new image set in Assets.xcassets and place image#3x.png and image#2x.png accordingly.
Don't forget plist.
NSLocationAlwaysUsageDescription and NSLocationWhenInUseUsageDescription
As always test on a real device.
The swizzle 🌀
//1
CustomPointAnnotation.swift
import UIKit
import MapKit
class CustomPointAnnotation: MKPointAnnotation {
var pinCustomImageName:String!
}
//2
ViewController.swift
import UIKit
import MapKit
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
#IBOutlet weak var pokemonMap: MKMapView!
let locationManager = CLLocationManager()
var pointAnnotation:CustomPointAnnotation!
var pinAnnotationView:MKPinAnnotationView!
override func viewDidLoad() {
super.viewDidLoad()
//Mark: - Authorization
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
pokemonMap.delegate = self
pokemonMap.mapType = MKMapType.Standard
pokemonMap.showsUserLocation = true
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = CLLocationCoordinate2D(latitude: 35.689949, longitude: 139.697576)
let center = location
let region = MKCoordinateRegionMake(center, MKCoordinateSpan(latitudeDelta: 0.025, longitudeDelta: 0.025))
pokemonMap.setRegion(region, animated: true)
pointAnnotation = CustomPointAnnotation()
pointAnnotation.pinCustomImageName = "Pokemon Pin"
pointAnnotation.coordinate = location
pointAnnotation.title = "POKéSTOP"
pointAnnotation.subtitle = "Pick up some Poké Balls"
pinAnnotationView = MKPinAnnotationView(annotation: pointAnnotation, reuseIdentifier: "pin")
pokemonMap.addAnnotation(pinAnnotationView.annotation!)
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print(error.localizedDescription)
}
//MARK: - Custom Annotation
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
let reuseIdentifier = "pin"
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseIdentifier)
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseIdentifier)
annotationView?.canShowCallout = true
} else {
annotationView?.annotation = annotation
}
let customPointAnnotation = annotation as! CustomPointAnnotation
annotationView?.image = UIImage(named: customPointAnnotation.pinCustomImageName)
return annotationView
}
}
There are a few issues you need to deal with.
MKMapView and annotations
Firstly, it is necessary to understand how MKMapView displays an annotation view from an annotation. There are
MKMapView - displays the map and manages annotations.
MKMapViewDelegate - you return data from specific functions to MKMapView.
MKAnnotation - contains data about a location on the map.
MKAnnotationView - displays an annotation.
An MKAnnotation holds the data for a location on the map. You create this data and hand it to MKMapView. At some point in the future, when the map view is ready to display the annotation it will call back to the delegate and ask it to create an MKAnnotationView for an MKAnnotation. The delegate creates and returns the view and the map view displays it. You specify the delegate in the storyboard, or in code e.g. mapView.delegate = self.
Location
Tracking the users location is complicated by:
Permission is needed from the user before location tracking is enabled.
There is a delay after the user allows tracking, until the user's location is available.
Location services might not even be enabled.
Your code needs to deal with authorisation by checking CLLocationManager.authorizationStatus, and implementing CLLocationManagerDelegate methods.
Note that to use requestWhenInUseAuthorization requires entry for NSLocationWhenInUseUsageDescription in Info.plist
Example
Example project on GitHub.
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
// Instance of location manager.
// This is is created in viewDidLoad() if location services are available.
var locationManager: CLLocationManager?
// Last location made available CoreLocation.
var currentLocation: MKUserLocation? {
didSet {
// Hide the button if no location is available.
button.hidden = (currentLocation == nil)
}
}
// Date formatter for formatting dates in annotations.
// We use a lazy instance so that it is only created when needed.
lazy var formatter: NSDateFormatter = {
let formatter = NSDateFormatter()
formatter.timeStyle = NSDateFormatterStyle.ShortStyle
formatter.dateStyle = NSDateFormatterStyle.ShortStyle
return formatter
}()
#IBOutlet var button: UIButton!
#IBOutlet var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
// Track the user's location if location services are enabled.
if CLLocationManager.locationServicesEnabled() {
locationManager = CLLocationManager()
locationManager?.delegate = self
locationManager?.desiredAccuracy = kCLLocationAccuracyBest
switch CLLocationManager.authorizationStatus() {
case .AuthorizedAlways, .AuthorizedWhenInUse:
// Location services authorised.
// Start tracking the user.
locationManager?.startUpdatingLocation()
mapView.showsUserLocation = true
default:
// Request access for location services.
// This will call didChangeAuthorizationStatus on completion.
locationManager?.requestWhenInUseAuthorization()
}
}
}
//
// CLLocationManagerDelegate method
// Called by CLLocationManager when access to authorisation changes.
//
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
switch status {
case .AuthorizedAlways, .AuthorizedWhenInUse:
// Location services are authorised, track the user.
locationManager?.startUpdatingLocation()
mapView.showsUserLocation = true
case .Denied, .Restricted:
// Location services not authorised, stop tracking the user.
locationManager?.stopUpdatingLocation()
mapView.showsUserLocation = false
currentLocation = nil
default:
// Location services pending authorisation.
// Alert requesting access is visible at this point.
currentLocation = nil
}
}
//
// MKMapViewDelegate method
// Called when MKMapView updates the user's location.
//
func mapView(mapView: MKMapView, didUpdateUserLocation userLocation: MKUserLocation) {
currentLocation = userLocation
}
#IBAction func addButtonTapped(sender: AnyObject) {
guard let coordinate = currentLocation?.coordinate else {
return
}
let reportTime = NSDate()
let formattedTime = formatter.stringFromDate(reportTime)
let annotation = MKPointAnnotation()
annotation.title = "Annotation Created"
annotation.subtitle = formattedTime
annotation.coordinate = coordinate
mapView.addAnnotation(annotation)
}
//
// From Bhoomi's answer.
//
// MKMapViewDelegate method
// Called when the map view needs to display the annotation.
// E.g. If you drag the map so that the annotation goes offscreen, the annotation view will be recycled. When you drag the annotation back on screen this method will be called again to recreate the view for the annotation.
//
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
guard !annotation.isKindOfClass(MKUserLocation) else {
return nil
}
let annotationIdentifier = "AnnotationIdentifier"
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(annotationIdentifier)
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
annotationView!.rightCalloutAccessoryView = UIButton(type: .DetailDisclosure)
annotationView!.canShowCallout = true
}
else {
annotationView!.annotation = annotation
}
annotationView!.image = UIImage(named: "smile")
return annotationView
}
}
check your image.png in your project bundle or Assets.xcassets
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
guard !annotation.isKind(of: MKUserLocation.self) else {
return nil
}
let annotationIdentifier = "AnnotationIdentifier"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationIdentifier)
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
annotationView?.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
annotationView!.canShowCallout = true
}
else {
annotationView!.annotation = annotation
}
annotationView!.image = UIImage(named: "image.png")
return annotationView
}
Do as follow may be work for you.
1) Create custom class for the Annotation Pin.
class CustomPointAnnotation: MKPointAnnotation {
var imageName: UIImage!
}
2)Define variable as below.
var locationManager = CLLocationManager()
3) Call below method in viewDidLoad()
func checkLocationAuthorizationStatus() {
if CLLocationManager.authorizationStatus() == .AuthorizedAlways {
map.showsUserLocation = false
} else {
locationManager.requestWhenInUseAuthorization()
}
}
4) Put below code in viewWillAppear()
self.map.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.delegate = self
dispatch_async(dispatch_get_main_queue(),{
self.locationManager.startUpdatingLocation()
})
5) Most important implement below method.
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if !(annotation is CustomPointAnnotation) {
return nil
}
let reuseId = "Location"
var anView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
if anView == nil {
anView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
anView!.canShowCallout = true
}
else {
anView!.annotation = annotation
}
let cpa = annotation as! CustomPointAnnotation
anView!.image = cpa.imageName
return anView
}
6) Execute below code where you you have received custom pin image
let strLat = "YOUR LATITUDE"
let strLon = "YOUR LONGITUDE"
let info = CustomPointAnnotation()
info.coordinate = CLLocationCoordinate2DMake(strLat.toDouble()!,strLon.toDouble()!)
info.imageName = resizedImage
info.title = dict!["locationName"]! as? String
self.map.addAnnotation(info)
From the code and according to the MapKit guide, your code look correct. I am thinking that it could be this line annotationView.image = UIImage(named: "image.png")
Is there a chance that image.png could be the wrong image name or not added in to the project when compile? Also just fyi, if you are using .xcassets, you does not have to add a .png.
As annotationView.image is a optional, when the image UIImage(named: "image.png") is nil, it will not crash but just render the default pin image.
If this is not the issue, please provide more info on the debugging steps that you have taken so the rest of us can understand better and help you. Cheers =)

Swift 3.0 Setting Annotation Pin Color for MapView

I am having trouble setting a pin color for my map annotation. I have a function in my MapView viewcontroller that pulls from an array from another view controller and depending on the case of the type, I want different pin colors for the map view. I am not sure how I can add the pin color information to the annotation within this switch statement. My understanding of annotations is rather weak so any explanations, rather than the solution itself, are greatly appreciated.
class ColorPointAnnotation: MKPointAnnotation {
var pinColor: UIColor
init(pinColor: UIColor) {
self.pinColor = pinColor
super.init()
}
}
func add(newLocation location_one:[String:Any]) {
let momentaryLat = (location_one["latitude"] as! NSString).doubleValue
let momentaryLong = (location_one["longitude"] as! NSString).doubleValue
var annotation = MKPointAnnotation()
switch location_one["type"] {
case "Tomorrow":
print("The pin color is red")
annotation = ColorPointAnnotation(pinColor: UIColor.red)
case "Next Week":
print("The pin color is green")
annotation = ColorPointAnnotation(pinColor: UIColor.green)
default:
print("The pin color is purple")
annotation = ColorPointAnnotation(pinColor: UIColor.purpleColor)
}
annotation.title = location_one["title"] as? String
annotation.coordinate = CLLocationCoordinate2D(latitude: momentaryLat as CLLocationDegrees, longitude: momentaryLong as CLLocationDegrees)
DispatchQueue.main.async {
self.map.addAnnotation(annotation)
}
self.map.centerCoordinate = annotation.coordinate
}
func mapView(_ map: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
// if (annotation is MKUserLocation) {
// return nil
// }
let identifier = "pinAnnotation"
var annotationView = map.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKPinAnnotationView
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView?.canShowCallout = true
let colorPointAnnotation = annotation as! ColorPointAnnotation
annotationView?.pinTintColor = colorPointAnnotation.pinColor
}
// else {
// annotationView?.annotation = annotation
//
// }
// map.showAnnotations(map.annotations, animated: true)
return annotationView
}
You need move your switch statement into the viewForAnnotation delegate method. Here you when you return a pin, you can customize the color and then return it.
Like so :
annotation.pinColor = MKPinAnnotationColorGreen;
Updated Answer :
You can subclass MKPointAnnotation, and add a property that stores the type of annotation.
When you create an annotation in your add method, set the property to what ever type of pin it is.
Now in the viewForAnnotation method, mapkit will give the annotation of your type. Look at the set property and determine which color pin to return.
Let me know if you want see some code.

Update image for user location on MKMapView

Im setting a custom image for the user location on a map like this:
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if annotation.isEqual(mapView.userLocation) {
let identifier = "User"
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)
if annotationView == nil{
annotationView = CustomPointAnnotation(annotation: annotation, reuseIdentifier: identifier)
annotationView!.canShowCallout = true
} else {
annotationView!.annotation = annotation
}
annotationView!.image = UIImage(named: userImage)
return annotationView
}
return nil
}
Ive change the image property, how can I tell the map to update the MKAnnotationView?
This solutions works for me:
let userLocation = mapView.view(for: mapView.userLocation)
userLocation?.image = UIImage(named: "newImage")
userLocation?.isHidden = true
userLocation?.isHidden = false
One of my answers - https://stackoverflow.com/a/57868438/7505665
I had similar problem and solution in my case was this code
self.mapView.showsUserLocation = false
self.mapView.showsUserLocation = true
I think you want to remove the annotations and then re-add them and that will force the map to update. Editing an existing annotation directly doesn't force the map to redraw.

Add custom annotations to MapKit

I am relatively new to Swift language. I know how to launch mapkit in my app with added annotations but I want to add a pin without the standard red pin but with a custom image that i have. Is there a simple way to make it happen? Thanks
You didn't add any code into your question so I am giving you an example code.
Use this delegate method viewForAnnotation for custom pin.
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if annotation is MKUserLocation {
//return nil so map view draws "blue dot" for standard user location
return nil
}
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier("pin")
if pinView == nil {
pinView = MKAnnotationView(annotation: annotation, reuseIdentifier: "pin")
pinView!.canShowCallout = true
//Set your image here
pinView!.image = UIImage(named: "mappin")
var calloutButton = UIButton.buttonWithType(.DetailDisclosure) as! UIButton
pinView!.rightCalloutAccessoryView = calloutButton
}
else {
pinView!.annotation = annotation
}
return pinView
}
Hope it will help.

Swift - Directions to Selected Annotation from Current Location in Maps

My app currently has a local search which adds annotations for the search results. I want to set it up where when you select the annotation and click the call out button, it will open in the Maps application with directions to the annotation from the current device location. I'm having a few problems with this.
First of all, my call out button on the annotation does not appear. Secondly, I don't think I am detecting the selected annotation correctly.
Here is my code for the search and selected annotation:
func performSearch() {
matchingItems.removeAll()
let request = MKLocalSearchRequest()
request.naturalLanguageQuery = searchText.text
request.region = mapView.region
let search = MKLocalSearch(request: request)
search.startWithCompletionHandler({(response:
MKLocalSearchResponse!,
error: NSError!) in
if error != nil {
println("Error occured in search: \(error.localizedDescription)")
} else if response.mapItems.count == 0 {
println("No matches found")
} else {
println("Matches found")
for item in response.mapItems as! [MKMapItem] {
println("Name = \(item.name)")
println("Phone = \(item.phoneNumber)")
self.matchingItems.append(item as MKMapItem)
println("Matching items = \(self.matchingItems.count)")
var annotation = MKPointAnnotation()
var coordinates = annotation.coordinate
annotation.coordinate = item.placemark.coordinate
annotation.title = item.name
self.mapView.addAnnotation(annotation)
}
}
})
}
func mapView(mapView: MKMapView!, annotationView view: MKAnnotationView!,
calloutAccessoryControlTapped control: UIControl!) {
if self.mapView.selectedAnnotations?.count > 0 {
if let selectedLoc = self.mapView.selectedAnnotations[0] as? MKAnnotation {
println("Annotation has been selected")
let currentLoc = MKMapItem.mapItemForCurrentLocation()
let mapItems = NSArray(objects: selectedLoc, currentLoc)
let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving]
MKMapItem.openMapsWithItems([selectedLoc, currentLoc], launchOptions: launchOptions)
}
}
}
Any help will be appreciated, thanks in advance.
For the first issue:
A callout button needs to be set explicitly in the viewForAnnotation delegate method (default red pins don't have one). Here's a simple example of one possible implementation:
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if annotation is MKUserLocation {
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.pinColor = .Purple
//next line sets a button for the right side of the callout...
pinView!.rightCalloutAccessoryView = UIButton.buttonWithType(.DetailDisclosure) as! UIButton
}
else {
pinView!.annotation = annotation
}
return pinView
}
For the second issue:
First, in calloutAccessoryControlTapped, the annotation is directly accessible using view.annotation so using the selectedAnnotations array in there is unnecessary.
Next, openMapsWithItems expects an array of MKMapItem objects but in the array you are passing ([selectedLoc, currentLoc]), selectedLoc is not an MKMapItem -- it is just some object that implements MKAnnotation.
Running this code will result in a crash with this error:
-[MKPointAnnotation dictionaryRepresentation]: unrecognized selector sent to instance
when the Maps app tries to use selectedLoc as if it was an MKMapItem.
Instead, you need to create an MKMapItem from the selectedLoc annotation. This can be done by first creating an MKPlacemark from the annotation using MKPlacemark(coordinate:addressDictionary:) and then creating an MKMapItem from the placemark using MKMapItem(placemark:).
Example:
func mapView(mapView: MKMapView!, annotationView view: MKAnnotationView!,
calloutAccessoryControlTapped control: UIControl!) {
let selectedLoc = view.annotation
println("Annotation '\(selectedLoc.title!)' has been selected")
let currentLocMapItem = MKMapItem.mapItemForCurrentLocation()
let selectedPlacemark = MKPlacemark(coordinate: selectedLoc.coordinate, addressDictionary: nil)
let selectedMapItem = MKMapItem(placemark: selectedPlacemark)
let mapItems = [selectedMapItem, currentLocMapItem]
let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving]
MKMapItem.openMapsWithItems(mapItems, launchOptions:launchOptions)
}