Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to change MKAnnotation Coordinates without knowing variable name?

I appreciate the question might seem odd but basically I am adding annotations to the map after pulling coordinates from a backend database. The amount of annotations being added vary depending on the user.

let details = Annotation(title: "\(userName)",
                                         locationName: "",
                                         coordinate: CLLocationCoordinate2D(latitude:convertLat!, longitude: convertlon!))

                self.mapView.addAnnotation(details as MKAnnotation)
                self.mapView.selectAnnotation(details, animated: true)

The trouble I am having is I would like to update the coordinates of the 'details' annotation at specific intervals but I am unable to access the 'details' annotation because of course it is out of scope.

Is it possible, for example, to access an annotation through its title name and change its coordinates accordingly?

The other alternative is to remove all annotations and recreate them with the updated coordinates but this is something I am trying to avoid.

It's probably worth noting that for a number of reasons I can't just simply create the details annotation outside off my methods.

Thanks.

UPDATED So I'm trying a slightly different approach that looks like this:

for annotation in mapView.annotations as [MKAnnotation] {

        if (annotation as AnyObject).title == "Title of annotation"   {

           annotation.title = "Change to something else"

    }
}

However I am unable to change the title as Swift is telling me it's a 'get only' property and I don't understand why.

Adding annotation to the mapView:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {

   // if (annotation is MKUserLocation) { return nil }

    let reuseID = "icon"
    var v = mapView.dequeueReusableAnnotationView(withIdentifier: reuseID)

    if v != nil {

        v?.annotation = annotation

    } else {

        v = MKAnnotationView(annotation: annotation, reuseIdentifier: nil)
        v?.image = snapShotImage
        v?.canShowCallout = true
}

 return v

}

like image 552
Chris Avatar asked Aug 29 '16 11:08

Chris


2 Answers

Create subclass of MKAnnotation.

class CustomAnnotation: MKAnnotation {
    var _title: String = "Title of annotation"
    override var title: String {
        get {
            return _title
        }
        set {
            self._title = newValue
        }
    }
}

Now when create annotation using your custom class.

let details = CustomAnnotation(title: "\(userName)",
                                         locationName: "",
                                         coordinate: CLLocationCoordinate2D(latitude:convertLat!, longitude: convertlon!))

As you have getter and setter methods for title property, now you can update the specific or all annotations (as you did using for-in loop;as stated in your question).

like image 169
pkc456 Avatar answered Nov 02 '22 05:11

pkc456


Without knowing the structure of the source class that holds the coordinates, you could create a class that contains both the source object and the created MKAnnotation. This class will use KVO via addObserver to observe any changes in the source coordinates and then apply them to the annotation: the same could be done for title/subtitles. Add the created annotation to the map as normal. Make sure that instances of the above class are retained by the view controller that owns the mapView so ARC doesn't reclaim everything!

Assuming you can still access and update the source, the UI will look after itself.

like image 31
pbc Avatar answered Nov 02 '22 05:11

pbc