Reputation: 29458
I add a pin where a user touches with this code:
func addPin(tap: UITapGestureRecognizer) {
if (tap.state == UIGestureRecognizerState.Ended) {
var coordinate = mapView.convertPoint(tap.locationInView(mapView), toCoordinateFromView: mapView)
let address = addressAnnotationLogic.createWithCoordinate(coordinate)
mapView.addAnnotation(address)
routeLogic.addAddressAnnotation(address, toRoute: currentRoute!)
// reverse geocode
let pinLocation = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(pinLocation!, completionHandler: {
(placemarks, error) -> Void in
if error != nil {
println("Reverse geocoder failed with error " + error.localizedDescription)
}
if placemarks.count > 0 {
let topResult = placemarks[0] as? CLPlacemark
self.addressAnnotationLogic.updateAnnotation(address, withPlacemark: topResult!)
}
})
}
}
My addressAnnotationLogic just creates a backing NSManagedObjectModel to save it, and my routeLogic just adds it to a route which is another NSManagedObjectModel. My delegate methods are pretty standard.
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if annotation is AddressAnnotation {
var annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "SimplePinIdentifier")
annotationView.enabled = true
annotationView.animatesDrop = true
annotationView.draggable = false
annotationView.pinColor = MKPinAnnotationColor.Red
annotationView.canShowCallout = true
return annotationView
}
return nil
}
After my first pin is added, if I touch the screen again, for some reason the initial pin moves just the slightest bit which doesn't seem right. It's more frustrating because later I draw an MKPolyline between points and then the pin will move just ever so slightly making the poly line look incorrect. What is this about? Why the pins move just a little bit after already being added to the MKMapView?
Upvotes: 3
Views: 655
Reputation: 5151
You should probably make the coordinate
property in your AddressAnnotation
class dynamic
.
class AddressAnnotation: NSObject, MKAnnotation {
var title = ""
// this works
dynamic var coordinate: CLLocationCoordinate2D
// this doesn't
// var coordinate: CLLocationCoordinate2D
init(_ coord:CLLocationCoordinate2D)
{
coordinate = coord
}
}
If this doesn't work, please post your code for the AddressAnnotation
class and the updateAnnotation
method.
Here's what I think happens:
Your annotation first gets the coordinate
that is translated from the screen coordinates of your first tap.
Then, in the asynchronous completion handler of your geocoder invocation, your updateAnnotation()
method is called.
I assume that you update the coordinate
of your AddressAnnotation
to the coordinate of the nearest Placemark in there.
Unfortunately, the Map View has probably already drawn your Pin at the original location when that update happens.
When the coordinate is updated asynchronously, the Map View does not notice it. Only when it redraws the annotation (prompted by the next tap), it picks up the updated coordinate (so you see the move from the first tap coordinate to the nearest place mark's coordinate).
Now, the Map View is actually trying to be notified of changes in its annotation's coordinates so that it can automatically redraw at the new coordinates.
For that it uses a technology called Key-Value-Observing. "Normal" Swift properties don't support that, however. Making them dynamic
does.
Upvotes: 5