MKMapView setRegion animated does not show animation

I have MKMapView with annotation pins . When the image is loaded, the search for the nearest pin will be distorted and the map will be enlarged, so both the user's location and the nearest output will be displayed. I do this with [map setRegion:region animated:YES]; . Everything works fine here. The same method is also called by clicking on the button that finds the user, and then does exactly what I just described.

I also have a search box with which the user can search for map points. When the user types one of the search results, the map sets the area so that the desired output is in the middle. Now there is something strange about this. I also set this region animated, at least I execute the same command as above. But if the map point is too far from the current visible part of the map, it does not display animation when the area changes. Am I missing something? I already looked at the documents "Apples", they do not mention anything regarding the maximum distance for animations.

I look forward to any help!


Update 1:
Just tested it again in the simulator. An interesting fact is that when you first search MapPoint , then select a search result that it doesn’t enliven. If I perform another search immediately after the first and select the result, it comes to life. As soon as I click on the location button, which returns the user to his location, and the nearest point does not setRegion: this setRegion: and the first search after that. But only in the Simulator, on my 4S, does it do exactly what I described in the original question above.


Update 2:
In the comments I was asked to provide approximate coordinates.
So, here are the coordinates for the first step (finding your own location and the nearest pin):
My location: 47.227131 / 8.264251
Nearest pin: 47.251347 / 8.357191
The distance between them is about 22 kilometers. The center of the card is the center between the two pins. The distance from the center to the screen border is 1.5 times the distance between two points, which means about 33 kilometers in this case.
And here is the set of coordinates for the second step (search for a map point and its selection):
Distorted Conclusion: 46.790680 / 9.818824
The distance to the border of the screen here is fixed at 500 meters.

+8
ios objective-c iphone mkmapview
source share
3 answers

I tested this problem with a simple demo application on the beta versions of iOS 6 and iOS 7. It turns out that displaying a map does not actually always liven up the transition between regions. It depends on how far the regions are. For example, the transition from Paris to London is not lively. But if you first zoom out a little and then move to London, it will be animated.

The documentation says:

animated: specify YES if you want the map view to display a transition to a new region or NO if you want the map to focus on the specified area immediately.

But, as we saw, we cannot rely on animation. We can only show the map view that the transition should be animated. MapKit decides whether the animation is appropriate. It tells the delegate if the transition will be animated in -(void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated .

To constantly animate a change in a region in all cases, you first need to plunge into the intermediate area. Let A be the region of the current display, and B be the region of the target. If there is an intersection between regions, you can go directly. (Convert MKCoordinateRegion to MKMapRect and use MKMapRectIntersection to find the intersection). If there is no intersection, calculate area C that spans both areas (use MKMapRectUnion and MKCoordinateRegionForMapRect ). Then first go to region C and into regionDidChangeAnimated go to region B.

Code example:

 MKCoordinateRegion region = _destinationRegion; MKMapRect rect = MKMapRectForCoordinateRegion(_destinationRegion); MKMapRect intersection = MKMapRectIntersection(rect, _mapView.visibleMapRect); if (MKMapRectIsNull(intersection)) { rect = MKMapRectUnion(rect, _mapView.visibleMapRect); region = MKCoordinateRegionForMapRect(rect); _intermediateAnimation = YES; } [_mapView setRegion:region animated:YES]; 

 -(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated { if (_intermediateAnimation) { _intermediateAnimation = NO; [_mapView setRegion:_destinationRegion animated:YES]; } } 

This helper method is taken from here.

 MKMapRect MKMapRectForCoordinateRegion(MKCoordinateRegion region) { MKMapPoint a = MKMapPointForCoordinate(CLLocationCoordinate2DMake( region.center.latitude + region.span.latitudeDelta / 2, region.center.longitude - region.span.longitudeDelta / 2)); MKMapPoint b = MKMapPointForCoordinate(CLLocationCoordinate2DMake( region.center.latitude - region.span.latitudeDelta / 2, region.center.longitude + region.span.longitudeDelta / 2)); return MKMapRectMake(MIN(ax,bx), MIN(ay,by), ABS(ax-bx), ABS(ay-by)); } 

WWDC 2013 Session 309 Entering a map in Vista explains how to make such complex transitions in iOS 7.

+13
source share

For those who have the same question and use Swift and use tableView:

I called setRegion after rejecting the tableView and it did not show the animation. This is my code before editing:

 dismiss(animated: true, completion: nil) a function that calls setRegion 

Then I changed it to:

 dismiss(animated: true, completion: { a function that calls setRegion }) 

This time it works.

0
source share

Here are the @Felix features rewritten in Swift 4:

 // MARK: - MapView help properties var destinationRegion: MKCoordinateRegion? var intermediateAnimation = false func center() { // Center map var initialCoordinates = CLLocationCoordinate2D(latitude: 49.195061, longitude: 16.606836) var regionRadius: CLLocationDistance = 5000000 destinationRegion = MKCoordinateRegionMakeWithDistance(initialCoordinates, regionRadius * 2.0, regionRadius * 2.0) centreMap(on: destinationRegion!) } private func mapRect(forCoordinateRegion region: MKCoordinateRegion) -> MKMapRect { let topLeft = CLLocationCoordinate2D(latitude: region.center.latitude + (region.span.latitudeDelta/2), longitude: region.center.longitude - (region.span.longitudeDelta/2)) let bottomRight = CLLocationCoordinate2D(latitude: region.center.latitude - (region.span.latitudeDelta/2), longitude: region.center.longitude + (region.span.longitudeDelta/2)) let a = MKMapPointForCoordinate(topLeft) let b = MKMapPointForCoordinate(bottomRight) return MKMapRect(origin: MKMapPoint(x:min(ax,bx), y:min(ay,by)), size: MKMapSize(width: abs(ax-bx), height: abs(ay-by))) } func centreMap(on region: MKCoordinateRegion) { var region = region var rect = mapRect(forCoordinateRegion: region) let intersection = MKMapRectIntersection(rect, mapView.visibleMapRect) if MKMapRectIsNull(intersection) { rect = MKMapRectUnion(rect, mapView.visibleMapRect) region = MKCoordinateRegionForMapRect(rect) intermediateAnimation = true } mapView.setRegion(region, animated: true) } // MARK: - MKMapViewDelegate func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) { if intermediateAnimation, let region = destinationRegion { intermediateAnimation = false mapView.setRegion(region, animated: true) } } 
0
source share

All Articles