Xernox
Xernox

Reputation: 1736

How to perform action when user taps on map using MapKit, Swift

I have custom views, that appear when user taps on annotation, but I don't know how to make those views disappear when user taps somewhere else on map. In Google Map SDK for iOS it would be didTapAtCoordinate and then I would set view.hidden = true.

I think it can be done using touchBegan, although I haven't used this function before? Although I would prefer MapKit version of Googles didTapAtCoordinate.

EDIT

class ViewController: UIViewController, MKMapViewDelegate {

    @IBOutlet weak var mapView: MKMapView!
    @IBOutlet weak var myCustomView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        myCustomView.hidden = true
        //MyAnnatationClass is my class where I store MKAnnatations with additional details
        let ann = MyAnnatationClass(coordinate: CLLocationCoordinate2D(latitude: 54.694084, longitude: 25.288782), title: "DEMO2", name: "Some Name")
        mapView.addAnnotation(ann)
   }

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

        let identifier = "id"

        if annotation.isKindOfClass(MyAnnatationClass.self) {

            var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)

            if annotationView == nil {

                annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: identifier)
                annotationView?.image = UIImage(named: "pin.png")
                annotationView!.canShowCallout = true
            } else {

                annotationView!.annotation = annotation
            }

            return annotationView
        }

        return nil
    }

    func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) {
        //Set view details
        let myAnn = view.annotation as! MyAnnatationClass
        someViewLabel.text = myAnn.name
        myCustomView.hidden = false

        let annotationTap = UITapGestureRecognizer(target: self, action: "tapRecognized:")
        annotationTap.numberOfTapsRequired = 1
        view.addGestureRecognizer(annotationTap)

        let selectedAnnotations = mapView.selectedAnnotations

        for annotationView in selectedAnnotations{
            mapView.deselectAnnotation(annotationView, animated: true)
        }
    }

    func mapView(mapView: MKMapView, didDeselectAnnotationView view: MKAnnotationView) {
        view.hidden = true 
    }

    func tapRecognized(gesture:UITapGestureRecognizer){

        let selectedAnnotations = mapView.selectedAnnotations

        for annotationView in selectedAnnotations{
            mapView.deselectAnnotation(annotationView, animated: true)
        }
    }
}

Currently, when I touch annotation, myCustomView appears and annotation disappears. If in didDeselectAnnotationView I change view to myCustomView then custom view never appears.

Upvotes: 0

Views: 3970

Answers (2)

MisterGreen
MisterGreen

Reputation: 156

I think Igor's answer https://stackoverflow.com/a/11455213/4205432 will be good for you, i just translated it to swift. you have a delegate method that you can use to know which annotation view was deselected and do your stuff there. as mentioned in Igor's answer you can add a boolean flag to identify if 'isShow' or not.

   func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) {

        let annotationTap = UITapGestureRecognizer(target: self, action: "tapRecognized")
        annotationTap.numberOfTapsRequired = 1
        view.addGestureRecognizer(annotationTap)

        let selectedAnnotations = mapView.selectedAnnotations

        for annotationView in selectedAnnotations{
            mapView.deselectAnnotation(annotationView, animated: true)
        }
    }

    func tapRecognized(gesture:UITapGestureRecognizer){

        let selectedAnnotations = mapView.selectedAnnotations

        for annotationView in selectedAnnotations{
            mapView.deselectAnnotation(annotationView, animated: true)
        }
    }

    func mapView(mapView: MKMapView, didDeselectAnnotationView view: MKAnnotationView) {

        view.hidden = true
    }

Upvotes: 1

Duncan C
Duncan C

Reputation: 131511

I suggest using the built-in annotation callout mechanism. You can create a custom callout view, and the system displays it in response to the user tapping on the annotation, and also animates it away if the user taps somewhere else.

The map view already makes extensive use of gestures so trying to add your own gesture handling on top is going to be hard.

Upvotes: 0

Related Questions