1
votes

I've been breaking my head over a strange piece of behaviour I am noticing when trying to display MKPointAnnotation's on an MKMapView in iOS 10. I found 2 related posts on StackOverflow, but neither actually answers the problem I am facing. They are:

  1. https://stackguides.com/questions/36760810/mkmapview-annotation-title-is-not-showing but this does not have any answer, and the issue seems slightly different as here the title NEVER shows while in my case it does show but with a weird workaround.
  2. https://stackguides.com/questions/33818285/ios-mapview-annotations-not-showing-for-pins but there the user just had forgotten to actually set a title. There is an interesting comment at the end though by @rockhammer that is somewhat related but not exactly: 'It appears that at the time an annotation is added to a map, the .title must have at least one character, even if it is a " ". Otherwise, even if .title is subsequently modified to be other than "", the label won't show.'

My situation: I have a function where when the user longpresses on the map an annotation will be added. The title is basically the first available line of the address found using a CLGeocoder().reverseGeocodeLocation(...) lookup. If all fails it will simply use the date. You will notice that the annotation is only added all the way at the end when it's absolutely sure there is text in the title. This makes the comment from the 2nd post mentioned above not fit this situation.

My problem: You will notice the line annotation.title = "BLAH" near the top. Without this line the annotation titles will not show up in the MKMapView, but only the pins will show!

@IBOutlet weak var map: MKMapView!

func longPress(gestureRecognizer: UIGestureRecognizer) {
    if gestureRecognizer.state == UIGestureRecognizerState.began {
        let touchPoint = gestureRecognizer.location(in: self.map)
        let coordinate = map.convert(touchPoint, toCoordinateFrom: self.map)
        let annotation = MKPointAnnotation()
        annotation.coordinate = coordinate
        annotation.title = "BLAH" //WITHOUT THIS THE TITLE NEVER SHOWS

        CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)) { (placemarks, error) in
            if error != nil {
                print(error!)
            } else {
                if let placemark = placemarks?[0] {
                    annotation.title = placemark.subThoroughfare != nil ? placemark.subThoroughfare! : ""
                    annotation.title = annotation.title! + (annotation.title! == "" ? "" : " ") + (placemark.thoroughfare != nil ? placemark.thoroughfare! : "")
                    if annotation.title == "" {
                        annotation.title = placemark.subLocality != nil ? placemark.subLocality! : ""
                        if annotation.title == "" {
                            annotation.title = placemark.subAdministrativeArea != nil ? placemark.subAdministrativeArea! : ""
                            if annotation.title == "" {
                                annotation.title = placemark.postalCode != nil ? placemark.postalCode! : ""
                                if annotation.title == "" {
                                    annotation.title = placemark.country != nil ? placemark.country! : ""
                                }
                            }
                        }
                    }
                }
            }
            if annotation.title == "" {
                annotation.title = "Added \(NSDate())"
            } //At this point a title is guaranteed to be set. Still, it never shows unless it is first 'initialised' with 'BLAH' or something at the beginning.
        }

        self.map.addAnnotation(annotation)
    }
}

If anyone can show me the logic and how/why this is happening, that'd be wonderful.

1

1 Answers

0
votes

You need to change 3 methods which are not correct; I do not known why this methods do not work.

I propose to you some other methods witch compile and work, normally, well. You need to:

  • change UIGestureRecognizerState.begantoUIGestureRecognizerState.Began;

  • change touchPoint = gestureRecognizer.location(in: self.map)to touchPoint = gestureRecognizer.locationInView(self.mapView);

  • and finally, change coordinate = mapView.convert(teste, toCoordinateFrom: self.mapView)to coordinate = mapView.convertPoint(touchPoint, toCoordinateFromView: self.mapView).

Finally your code should look like this:

@IBOutlet weak var map: MKMapView!


func longPress(gestureRecognizer: UIGestureRecognizer) {
    if gestureRecognizer.state == UIGestureRecognizerState.Began {     // And not .began
        let touchPoint: CGPoint = gestureRecognizer.locationInView(self.map)   //And not location(in: self.map)
    //let coordinate = mapView.convert(teste, toCoordinateFrom: self.map)
    let coordinate = map.convertPoint(touchPoint, toCoordinateFromView: self.map)
        let annotation = MKPointAnnotation()
        annotation.coordinate = coordinate
        //annotation.title = "BLAH" //WITHOUT THIS THE TITLE NEVER SHOWS

        CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)) { (placemarks, error) in
            if error != nil {
                print(error!)
            } else {
                if let placemark = placemarks?[0] {
                    annotation.title = placemark.subThoroughfare != nil ? placemark.subThoroughfare! : ""
                    annotation.title = annotation.title! + (annotation.title! == "" ? "" : " ") + (placemark.thoroughfare != nil ? placemark.thoroughfare! : "")
                    if annotation.title == "" {
                        annotation.title = placemark.subLocality != nil ? placemark.subLocality! : ""
                        if annotation.title == "" {
                            annotation.title = placemark.subAdministrativeArea != nil ? placemark.subAdministrativeArea! : ""
                            if annotation.title == "" {
                                annotation.title = placemark.postalCode != nil ? placemark.postalCode! : ""
                                if annotation.title == "" {
                                    annotation.title = placemark.country != nil ? placemark.country! : ""
                                }
                            }
                        }
                    }
                }
            }

            if annotation.title == "" {
                annotation.title = "Added \(NSDate())"
            } //At this point a title is guaranteed to be set. Still, it never shows unless it is first 'initialised' with 'BLAH' or something at the beginning.
        }

        self.map.addAnnotation(annotation)
    }
}