Search code examples
swiftmapkitmkannotationmapkitannotation

How programmatically select a specific annotation in Mapkit - Swift


I'm developing a map in MapKit/Swift 4 where i have a lot of annotations. User could select with a Picker View what annotation (just 1) he wants, and the annotation will be called (as if he had pushed on it). If it's easier, we could consider to change the color of this annotation point. The key point is to highlight this particular annotation among a lot of annotations.

After some search, i ve found this function

func selectAnnotation(_ annotation: MKAnnotation, animated: Bool)

I've implemented this following function :

func selectPoints() {
    print("selectPoints called")
    let annotation1 = MKPointAnnotation()
    annotation1.coordinate = CLLocationCoordinate2D(latitude: 48.8596833, longitude: 2.3988939)
    annotation1.title = "Temple"
    annotation1.subtitle = "\(annotation1.coordinate.latitude), \(annotation1.coordinate.longitude)"
    mapView.addAnnotation(annotation1)

    mapView.selectAnnotation(annotation1, animated: true)
}

So it's working if i create a new annotation, but how could i select previous annotations points ? But i don't have any idea or hint to go forward.

Thanks for you help.

EDIT: Part of code to input annotations.

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    if let annotation = annotation as? Artwork {

        let reuseId = "pin"
        var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)

        if pinView == nil {
            pinView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
            pinView!.canShowCallout = true
            pinView!.isDraggable = false
            pinView!.calloutOffset = CGPoint(x: 0, y: 0)
            pinView!.rightCalloutAccessoryView = UIButton(type: .detailDisclosure) as UIView

        }
        else {
            pinView!.annotation = annotation
        }

    }

    return nil
}

Solution

  • You can do this with the annotations property of your mapView. As a rough outline, in your view controller you would have some code like this:

    func beginAnnotationSelection() {
        self.view.addSubview(self.pickerView)
    }
    
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }
    
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return self.mapView.annotations.count
    }
    
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return self.mapView.annotations[row].title ?? "No title"
    }
    
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        self.mapView.selectAnnotation(self.mapView.annotations[row], animated: true)
    }
    

    Note that this assumes that mapView and pickerView are instance variables of your view controller, and that the picker view's data source and delegate are set to your view controller. I don't do any frame setup for the picker view or anything, so you'll have to implement all that yourself.