I have multiple annotations all working correctly and showing everything I want them to. However I want to display a detail view when the annotation callout accessory is pressed. I have it all working to the point where the details passed into the calloutAccessoryControlTapped function, which are only last to be loaded at run time and not of the annotation pressed.
I have scoured the internet for an answer to this and can't seem to find the solution.
Please help!!
P.S. Please excuse the code being messy at some points, I've been messing about with it, A LOT!!
class SecondViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
class CustomPointAnnotation: MKPointAnnotation {
var imageName: String!
var ID: String!
}
@IBOutlet weak var mapSeg: UISegmentedControl!
@IBOutlet weak var mainMapView: MKMapView!
@IBOutlet weak var webView: UIWebView!
var manager = CLLocationManager()
let signalsArray = ["MC 411 Signal", "MC 413 Signal ", "MC 414 Signal","MC 415 Signal", "MC 416 Signal", "MC 417 Signal", "MC 434 Signal", "MC 436 Signal", "MC 438 Signal"]
var segueIdentity: String?
override func viewDidLoad() {
super.viewDidLoad()
println("screen loaded")
mainMapView.delegate = self
loadUrl()
var latitude:CLLocationDegrees = 55.691203
var longitude:CLLocationDegrees = -3.668746
var latDelta:CLLocationDegrees = 0.002 //zoom level, smaller = closer
var lonDelta:CLLocationDegrees = 0.002
var span:MKCoordinateSpan = MKCoordinateSpanMake(latDelta, lonDelta)
var location:CLLocationCoordinate2D = CLLocationCoordinate2DMake(latitude, longitude)
var region:MKCoordinateRegion = MKCoordinateRegionMake(location, span)
var station = CustomPointAnnotation()
mainMapView.mapType = MKMapType.Hybrid
mainMapView.setRegion(region, animated: true)
mainMapView.frame = CGRectMake(19, 72, 984, 321)
webView.frame = CGRectMake(12, 397, 999, 321)
//add a pin to the location
station.coordinate = location
station.title = "Carstairs Train Station"
station.subtitle = "Motherwell Panel 6"
station.imageName = "devil"
station.ID = "station"
mainMapView.addAnnotation(station)
var sig1 = CustomPointAnnotation()
var sig1Location:CLLocationCoordinate2D = CLLocationCoordinate2DMake(55.690905, -3.66723)
sig1.coordinate = sig1Location
sig1.title = signalsArray [2]//MC414
sig1.subtitle = "Caution, short signal section to MC 434"
sig1.imageName = "GRS"
sig1.ID = "sig1"
mainMapView.addAnnotation(sig1)
var sig2 = CustomPointAnnotation()
var sig2Location:CLLocationCoordinate2D = CLLocationCoordinate2DMake(55.688745, -3.662528)
sig2.coordinate = sig2Location
sig2.title = signalsArray [6]//MC434
//sig2.subtitle = ""
sig2.imageName = "devil"
sig2.ID = "sig2"
mainMapView.addAnnotation(sig2)
var sig3 = CustomPointAnnotation()
var sig3Location:CLLocationCoordinate2D = CLLocationCoordinate2DMake(55.691119, -3.668915)
sig3.coordinate = sig3Location
sig3.title = signalsArray [3]//MC415
//sig3.subtitle = ""
sig3.imageName = "GRS"
sig3.ID = "sig3"
mainMapView.addAnnotation(sig3)
var sig4 = CustomPointAnnotation()
var sig4Location:CLLocationCoordinate2D = CLLocationCoordinate2DMake(55.691087, -3.668950)
sig4.coordinate = sig4Location
sig4.title = signalsArray [5]//MC417
//sig4.subtitle = ""
sig4.imageName = "GRS"
sig4.ID = "sig4"
mainMapView.addAnnotation(sig4)
var sig5 = CustomPointAnnotation()
var sig5Location:CLLocationCoordinate2D = CLLocationCoordinate2DMake(55.690856, -3.667783)
sig5.coordinate = sig5Location
sig5.title = signalsArray [4]//MC416
//sig5.subtitle = ""
sig5.imageName = "GRS"
sig5.ID = "sig5"
mainMapView.addAnnotation(sig5)
}
//Add a picture and button to annotation pin
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView!{
if !(annotation is CustomPointAnnotation){
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!.animatesDrop = true
pinView!.pinColor = MKPinAnnotationColor.Purple
pinView!.rightCalloutAccessoryView = UIButton.buttonWithType(UIButtonType.DetailDisclosure) as UIButton
}else {
}
let cpa = annotation as CustomPointAnnotation
var imageview = UIImageView(frame: CGRectMake(0, 0, 45, 45))
var segueId = cpa.ID
pinView!.leftCalloutAccessoryView = imageview
imageview.image = UIImage(named: cpa.imageName)
println(segueId)
segueIdentity = segueId
return pinView
}
func mapView(mapView: MKMapView!, annotationView: MKAnnotationView!, calloutAccessoryControlTapped control: UIControl!) {
if control == annotationView.rightCalloutAccessoryView {
println("Right accessory pressed with " + segueIdentity!)
pinSelected()
}
}
func mapView(mapView: MKMapView!, didDeselectAnnotationView view: MKPointAnnotation) {
println("selected annotation = " + segueIdentity!)
}
func pinSelected(){
UIView .animateWithDuration(0.5, animations: {
self.mainMapView.frame = CGRectMake(19, 72, 984, 595)
self.webView.frame = CGRectMake(12, 670, 999, 50)
})
println("pinselected fired with " + (segueIdentity)!)
self.performSegueWithIdentifier("pinSegue", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "pinSegue"){
println("prepare for segue fired! with " + (segueIdentity)!)
/*CustomPointAnnotation annotationView = sender
segue.destinationViewController setAnnotation*/
}
}
A number of your delegate methods are referencing segueIdentity
, which you set in viewForAnnotation
. You should not be referencing these class properties in order to know which annotation was tapped.
You should instead determine the appropriate annotation by taking the annotation view passed to you, look at the annotation
property, and then access your custom annotation's properties (e.g. the ID
property) at that point.
func mapView(mapView: MKMapView!, annotationView view: MKAnnotationView!, calloutAccessoryControlTapped control: UIControl!) {
if let annotation = view.annotation as? CustomPointAnnotation {
let identifier = annotation.ID
// now use `identifier` here, not `segueIdentity`
}
}
Frankly, I'd be inclined to retire the segueIdentity
property entirely.
Your if pinView == nil
needs and else
clause, or else the recycled annotation view will continue to reference the old annotation, e.g.
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
pinView!.pinColor = MKPinAnnotationColor.Purple
pinView!.rightCalloutAccessoryView = UIButton.buttonWithType(UIButtonType.DetailDisclosure) as UIButton
} else {
pinView!.annotation = annotation
}