2

What happens is I type in an address in the search field and click go. The location is found and the map zooms in. I click on the pin image and the title bubble pops up and shows the title.

I created a property "pin" to be a reference to the title property. After dragging to a new location has completed I set the property title label using the reference to the new location. In NSLog the property is showing as changed. But when I tap drag to a new location and dragging has ended the same original value of the title property remains unchanged.

I've looked at tons of questions about similar things and nothing is working.

Here is my GO button method:

  @IBAction func didTapGoButton(sender: UIButton) {
        self.spinnerContainer.hidden = false
        var geocoder = CLGeocoder()
        geocoder.geocodeAddressString(searchField.text, {(placemarks: [AnyObject]!, error: NSError!) -> Void in
            if let placemark = placemarks?[0] as? CLPlacemark {


                var region = self.mapView.region as MKCoordinateRegion
                region.center = placemark.location.coordinate
                region.span.longitudeDelta = 0.0144927536
                region.span.latitudeDelta = 0.0144927536

                self.mapView.zoomEnabled = true
                self.mapView.scrollEnabled = true
                let pa = MKPointAnnotation()
                pa.coordinate = placemark.location.coordinate
                pa.title = "\(placemark.name), \(placemark.locality), \(placemark.country)"

                self.spinnerContainer.hidden = true
                self.mapView.addAnnotation(pa)
                self.pin = pa
                self.mapView.setRegion(region, animated: true)
                self.annotationTitle = pa.title
                self.searchField.text = ""

                //self.mapView.selectAnnotation(pa, animated: true)

                var newLocation = CLLocation(latitude: pa.coordinate.latitude, longitude: pa.coordinate.longitude)
                var geocoder = CLGeocoder()
                geocoder.reverseGeocodeLocation(newLocation, completionHandler: { (placemarks: [AnyObject]!, error: NSError!) -> Void in
                    if let placemark = placemarks?[0] as? CLPlacemark {


                      //  let pa = MKPointAnnotation()
                        pa.coordinate = placemark.location.coordinate
                        pa.title = "\(placemark.name), \(placemark.locality), \(placemark.administrativeArea), \(placemark.country), \(placemark.postalCode)"

                        NSLog("\(pa.title)")
                        self.addressFromCoordinates.text = pa.title
                        self.noAddressLabel.hidden = true

                    }
                })


            }

        })
    }

My viewForAnimation:

func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {

    if annotation.isKindOfClass(MKUserLocation) {
        return nil
    }

    let reuseId = "pin"
    var pin = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)

    if pin == nil {
        NSLog("PIN NIL")
        pin = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
        pin.image = UIImage(named: "pin")
        pin.draggable = true
        pin.canShowCallout = true

    }
    else
    {
        NSLog("PIN NOT NIL")
        pin.annotation = annotation
    }
    return pin;
}

my didChangeDragState method:

 func mapView(mapView: MKMapView!, annotationView view: MKAnnotationView!, didChangeDragState newState: MKAnnotationViewDragState, fromOldState oldState: MKAnnotationViewDragState) {
        if newState == MKAnnotationViewDragState.Starting
        {
            view.dragState = MKAnnotationViewDragState.Dragging
        }
        else if newState == MKAnnotationViewDragState.Ending || newState == MKAnnotationViewDragState.Canceling
        {
            view.dragState = MKAnnotationViewDragState.None


            var newLocation = CLLocation(latitude: self.pin.coordinate.latitude, longitude: self.pin.coordinate.longitude)

            var geocoder = CLGeocoder()
            geocoder.reverseGeocodeLocation(newLocation, completionHandler: { (placemarks: [AnyObject]!, error: NSError!) -> Void in
                if let placemark = placemarks?[0] as? CLPlacemark {

                    let pa = MKPointAnnotation()
                    pa.coordinate = placemark.location.coordinate
                    pa.title = "\(placemark.name), \(placemark.locality), \(placemark.administrativeArea), \(placemark.country), \(placemark.postalCode)"

                    self.annotationTitle = pa.title

                    self.addressFromCoordinates.text = pa.title
                    self.editAddressButton.hidden = false
                    self.noAddressLabel.hidden = true
                }
            })
            NSLog("\(self.pin.coordinate.latitude), \(self.pin.coordinate.longitude)")
        }
    }

Is there some sort of refresh that needs to be done to the map view after dragging?

Thanks for your time

LondonGuy
  • 10,778
  • 11
  • 79
  • 151

1 Answers1

4

In didChangeDragState, this code:

let pa = MKPointAnnotation()
pa.coordinate = placemark.location.coordinate
pa.title = "\(placemark.name), \(placemark.locality), \(placemark.administrativeArea), \(placemark.country), \(placemark.postalCode)"

self.annotationTitle = pa.title

is not updating the title of the annotation just dragged because:

  1. The pa in pa.title = ... is referring to a new instance of MKPointAnnotation which is not connected in any way to the annotation just dragged. The let pa = MKPointAnnotation() line creates a new instance of an MKPointAnnotation. This new instance just exists locally in memory and is not even added to the map.

  2. The update to self.annotationTitle has no effect on the title of the annotation instance that was just dragged because annotationTitle is just some separate string variable you've declared and the original MKPointAnnotation that was added to the map and just dragged has no knowledge or connection whatsoever with annotationTitle (the fact that annotationTitle was initially set equal to the annotation's title in the didTapGoButton does not somehow "link" the two strings together).


In didTapGoButton, you are saving a reference to the annotation object that is actually added (and then dragged) in the pin variable. This pin variable is the reference you can use to update the title of the annotation that was dragged (assuming you will only have one annotation at a time).

So in didChangeDragState, change the code shown above to:

self.pin.coordinate = placemark.location.coordinate
self.pin.title = "\(placemark.name), \(placemark.locality), \(placemark.administrativeArea), \(placemark.country), \(placemark.postalCode)"

self.annotationTitle = self.pin.title


However, for your requirements, note that it's not really necessary to keep your own reference to the annotation in the first place...

In didChangeDragState, you can get access to the annotation that was dragged directly from the view argument that is passed into the method. For example:

let ann = view.annotation as MKPointAnnotation
ann.coordinate = placemark.location.coordinate
ann.title = "\(placemark.name), \(placemark.locality), \(placemark.administrativeArea), \(placemark.country), \(placemark.postalCode)"

self.annotationTitle = ann.title


Side Note:
After dragging the annotation and reverse geocoding the new location, there is a good possibility that the geocoded coordinates will be different than where the user dragged the annotation to. This happens because the nearest geocoded address may be slightly further from where the annotation was dragged to. So what will happen is the annotation will move a bit after the user finishes dragging. If you'd rather keep the annotation exactly where the user dragged it, don't update the annotation's coordinate in the geocoder's completion block and only update the title. You may want to set the title to something like "near xyz" if the geocoded address is X meters or more away from the actual coordinates.

  • Thanks Anna. This worked instantly. Found the side note very helpful. Is it possible to edit the font size of the title via ann.title. It won't let me call sizeWithFonts etc. – LondonGuy Sep 15 '14 at 13:44
  • There's no easy way I know of to change the title's font. Unfortunately, I think you'd have to create a custom callout view which can be tedious. –  Sep 15 '14 at 13:46