1

I try to make a simple map with annotations,but when I try to run it, the images of detailCalloutAccessoryView are the same, but I'm sure I put two different images, How did this happen? Or does anyone have a better way to do this?

   var tripspot:[tripSpot] = [
    tripSpot( title: "1", coordinate: CLLocationCoordinate2DMake(24.149062, 120.684891),  location: "台中市北區一中街", type: "rare",cllocation:CLLocation(latitude: 24.181143,  longitude: 120.593158),image : "025"),
    tripSpot( title: "2", coordinate: CLLocationCoordinate2DMake(24.180407, 120.645086), location:"台中逢甲", type: "rare",cllocation:CLLocation(latitude: 24.180407,  longitude: 120.645086),image : "007")]
   // Build LocationManager
let locationManager = CLLocationManager()


 override func viewDidLoad() {
    super.viewDidLoad()


    // set data
    setupData()

}

func setupData(){
    for aSpot in tripspot {
            //set annotation
            let coordinate = aSpot.coordinate
            let title = aSpot.title
            let type = aSpot.type

            //set annotation
            let tripSpotAnnotation = MKPointAnnotation()
            tripSpotAnnotation.coordinate = coordinate
            tripSpotAnnotation.title = title
            tripSpotAnnotation.subtitle = type
            mapView.addAnnotations([tripSpotAnnotation])



        }
    }
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView?
{
    if annotation.isKindOfClass(MKUserLocation)
    {

        return nil
    }

    var view = mapView.dequeueReusableAnnotationViewWithIdentifier("annotationIdentifier")as? MKPinAnnotationView

    if view == nil
    {
        view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "annotationIdentifier")
        view?.canShowCallout = true
        view?.sizeToFit()
    }
    else{
        view!.annotation = annotation
    }
    for aSpot in tripspot{

        // set pinview
        let detailCalloutAccessoryView = UIImageView(frame: CGRectMake(0, 0, 53, 53))
        detailCalloutAccessoryView.image = UIImage(named: aSpot.image!)
        view?.detailCalloutAccessoryView = detailCalloutAccessoryView

    view?.pinTintColor = pinColor(annotation.subtitle!!)
    }
    return view
    }

thanks for any advice.

Johnny Hsieh
  • 856
  • 2
  • 10
  • 23
  • Unrelated, I might suggest you follow Cocoa naming conventions and give your `class` and `struct` types a name that starts with an uppercase letter (e.g. `TripSpot`). It makes it more clear when you're referring to a type and when you're referring to an instance of that type. – Rob Jul 14 '16 at 21:18

1 Answers1

1

You should not iterate through the whole array of tripSpot in viewForAnnotation. This method is for a particular annotation, but the way this is written, it's going to repeatedly set (and reset) the detail accessory for every annotation to be each image for every aSpot in tripspot, effectively giving every annotation the same detail accessory as the last tripspot (and doing so inefficiently).

Instead, make your annotation a subclass of MKPointAnnotation and add a property so it knows which image to use for a given annotation. If tripspot is an array of reference types, you might just add a property to refer to the relevant tripspot entry (from which it can then identify which image to show). And then, viewForAnnotation should retrieve that property from your custom annotation subclass rather than iterating through tripspot array. Also, by including a reference to the underlying tripspot entry, you also now have the capability of having the "did select detail accessory" routine to now know which tripspot it's associated with, and take the appropriate action.

As an aside, I don't know how many potential annotations there are, but it might be more prudent to save the name of the image in tripspot array, rather than the image itself. Images are relatively large and you risk running into memory issues if you have lots of annotations. It's generally more prudent to instantiate your UIImage objects as needed, rather than populating an array with the actual images.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Hi @Rob, Im not quite understand your explanation, do you mean I need to add every image to each annotation? sorry, English is not my native language, it little bit difficult for me to fully understand. – Johnny Hsieh Jul 14 '16 at 20:10
  • @JohnnyHsieh - Perhaps easier, I might consider just making your `TripSpot` class conform to `MKAnnotation`, and then you can add it directly to your map, bypassing `MKPointAnnotation` altogether. – Rob Jul 14 '16 at 22:12
  • `class tripSpot: NSObject, MKAnnotation{ var title: String? var coordinate: CLLocationCoordinate2D var image : String? var location: String? var type: String? var cllocation: CLLocation init(title:String , coordinate: CLLocationCoordinate2D , location: String, type: String,cllocation: CLLocation, image: String ){ self.title = title self.coordinate = coordinate self.image = image self.location = location self.type = type self.cllocation = cllocation } }` – Johnny Hsieh Jul 15 '16 at 01:28
  • I has already set `tripSpot` as MKAnootation @Rob, so should I delete the code `//set annotation let tripSpotAnnotation = MKPointAnnotation() tripSpotAnnotation.coordinate = coordinate tripSpotAnnotation.title = title tripSpotAnnotation.subtitle = type` ? – Johnny Hsieh Jul 15 '16 at 01:37
  • If `TripSpot` conforms to `MKAnnotation`, then you don't need `MKPointAnnotation` at all. You can just pass your array of `TripSpot` objects to `mapView.addAnnotations`. And when you go to set the accessory view, your annotation _is_ you `TripSpot`, so you have access to the appropriate image, without needing to go back to that array again. – Rob Jul 15 '16 at 02:37
  • thanks for your kind response @Rob I don't have clear mind with array. Sorry for asking so many stupid question. I can just do mapView.addAnnotations(tripSpot) right now. And trying solve image problem. – Johnny Hsieh Jul 15 '16 at 03:01
  • Done! Thank you@Rob! – Johnny Hsieh Jul 15 '16 at 03:18