2017-02-10 12 views
17

Mam MKMapView z 2 przyciskami: powiększ i pomniejsz.setRegion: MKMapView przestaje reagować

Zauważyłem, że kiedy ich używam, nie mogę uszczypnąć mapy, aby powiększyć, dopóki animacja nie zostanie wykonana.

Mam guziki podpięte do setRegion na mniejszej lub większej rozpiętości niż jest teraz.

Próbowałem dodać do mojej mapy UIPinchGestureRecognizer, aby zatrzymać animację i zezwolić na uszczypnięcie. Oto, jak to zrobiłem:

Dodałem zmienną Bool, która określa, czy mapa jest aktualnie animowana po dotknięciu przycisków.

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

zastąpić setRegion tak:

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 
} 

te działają w zatrzymanie animacji, ale szczypta nie jest rozpoznawany przez mapę sama, aby powiększyć, choć to zrobić:

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

Domyślam się, że setRegion w pinchRecognized go zrywa, ale nie wiem, jak inaczej zatrzymać animację.

Zgodnie z wnioskiem, kod przycisku, oba przyciski użyć tej metody, powiększanie korzysta 0,5, pomniejszyć wykorzystuje 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: Próbowałem ustawienie setRegion (ten, który zatrzymuje animację) w gestureRecognizer:shouldRecognizeSimultaneouslyWith:, ale nie jest wywoływana podczas animowania mapy.

Edit: Po wypróbowaniu co @robinb zasugerował, zobaczyłem, że moje adnotacje zaktualizować szybciej niż mój samej mapie, co sugeruje, że region zostanie ustawiony, to po prostu czeka na coś wizualnie zaktualizować mapę.

+0

Możesz opublikować przycisk kod metoda? – CodeChanger

+0

@CodeChanger Zaktualizował pytanie – vrwim

+0

jakiś szczególny powód do przesłonięcia setRegion: funkcja? –

Odpowiedz

2

Urządzenia do rozpoznawania gestów nie wyświetlają się w widokach animowanych. Przytrzymaj widoki w zmiennej/tablicy w ViewController. Użyj kodu w tym poście do wykonywania animacji: https://stackoverflow.com/a/13814789/3970581

Oto testproject: animacje https://github.com/DuncanMC/iOS-CAAnimation-group-demo

+0

Pomyślałem, że to zadziała, ale użycie 'setRegion' na mapie z narzędzia do rozpoznawania gestów nie wydaje się aktualizować mapy. Przejście przez kod nie ujawnia żadnych błędów, "setRegion" jest aktualizowany z odpowiednimi wartościami, po prostu nie aktualizuje regionu. – vrwim

1

MapView set isUserInteractionEnabled false na początku, jednak jeśli chcesz siłą, że można podklasy MKMapView i zastąpić UIView za touchesBegan metoda reagowania na interakcje użytkowników. Tam możesz najpierw wywołać setCenter/setRegion (wartości początkowe lub docelowe) bez animacji, aby przerwać/zakończyć trwającą animację i ustawić wartość true dla wartości IsUserInteractionEnabled.

Aplikacja MKMapView używa CATiledLayer i niestety nie ma łatwego sposobu na uzyskanie regionu i/lub środka mapy w momencie przerwania. Z drugiej strony, zauważyłem, że czas trwania animacji jest stała, choć prywatne, dzięki czemu można korzystać z programatora, aby lepiej przypuszczenie regionu mapie kiedy touchesBegun nazywa

private var isAnimating: Bool = false 

override func setRegion(_ region: MKCoordinateRegion, animated: Bool) { 
    isAnimating = animated 
    ... 
} 

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 
    if isAnimating { 
     isAnimating = false 
     let region = // Destination region or the approximate region where the animation reached at this moment (although this is a nightmare todo) 
     setRegion(region: region, animated: false) // or use setCenter 
     isUserInteractionEnabled = true 
    } 
} 
+0

Daje to ten sam rezultat, mapa używa setRegion(), która przerywa bieżące szczypanie, które właśnie zacząłeś. – vrwim