Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

setRegion: MKMapView becomes unresponsive

Tags:

ios

swift

I have an MKMapView with 2 buttons on it: zoom in and zoom out.

I noticed that when I use them, I can't pinch the map to zoom anymore until the animation is done.

I have my buttons hooked up to setRegion on a smaller or larger span than it is now.

I tried adding a UIPinchGestureRecognizer to my map to stop the animation and allow the pinch to work. Here is how I did that:

I added a Bool variable that keeps whether the map is currently animating from a tap on the buttons.

func pinchRecognized() {
    if animating {
        var region = self.region
        region.span.latitudeDelta += 0.001
        setRegion(region, animated: false)
        animating = false
    }
}

I override setRegion like this:

override func setRegion(_ region: MKCoordinateRegion, animated: Bool) {
    if (animated)
    {
        animating = true
        super.setRegion(region, animated: animated)

        perform(#selector(noLongerAnimating), with: nil, afterDelay: 1)
    }
    else
    {
        super.setRegion(region, animated: animated)
    }
}

func noLongerAnimating() {
    animating = false
}

These work in stopping the animation, but the pinch is not recognised by the map itself to zoom, even though I do this:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
}

I guess the setRegion in pinchRecognized breaks it, but I don't know how else to stop the animation.

As requested, the button code, both buttons use this method, zoom in uses 0.5, zoom out uses 2:

func zoomTo(delta: Double, animated: Bool) {
    var region = self.region
    var span = region.span

    span.latitudeDelta *= delta
    span.longitudeDelta *= delta
    if (span.latitudeDelta < 180 && span.longitudeDelta < 180)
    {
        region.span = span
        setRegion(region, animated: animated)
    }
}

Edit: I tried setting the setRegion (the one that stops the animation) in gestureRecognizer:shouldRecognizeSimultaneouslyWith:, but there it doesn't get called while animating the map.

Edit: After trying what @robinb suggested, I saw that my annotations update quicker than my map itself, suggesting that the region gets set, it just waits for something to visually update the map.

like image 543
vrwim Avatar asked Feb 10 '17 13:02

vrwim


1 Answers

Gesture recognizers don't fire on views that are being animated. Hold the views in a variable/array at the ViewController. Use the code in this post to execute the animations: https://stackoverflow.com/a/13814789/3970581

Here is the testproject: https://github.com/DuncanMC/iOS-CAAnimation-group-demo

like image 89
Robin Bruneel Avatar answered Oct 04 '22 03:10

Robin Bruneel