MKMapView scope is interrupted after changing orientation in iOS7

We had problems with the MKMapView scope in iOS7.

After our application has started, and the device has changed the orientation of the interface several times, the values ​​returned by map.region become very strange. They tend to have a reasonable longitude range, but a small latitude range or vice versa, as if the map had the impression that its borders were reduced to a narrow rectangle along one edge of the screen. The actual boundaries and scope of MKMapView is still reasonable after this has happened.

It was possible to get around some of the problems this causes by calculating our area from the actual borders of the map, but we still have a couple of problems that we cannot fix. For example, when annotating is used to call up its leader, the map will sometimes pan to move the leader to that small part of the screen that he thinks is occupying.

Has anyone else experienced this issue?

Our pads for implementing a workaround below if they are useful:

+(void)setMap: (MKMapView*) map region:(MKCoordinateRegion) region { CGRect realBounds = map.bounds; MKCoordinateRegion claimedRegion = map.region; // the map claimed region, which is wonkily different after a rotate in ios7 CGRect claimedBounds = [map convertRegion:claimedRegion toRectToView:map]; // the bounds which the map thinks its region occupies // if we want region to map to realBounds, but the map thinks it is only claimedBounds big, what // reduced region will map to claimedBounds ? MKCoordinateRegion reducedRegion = [Utilities sliceRegion: region inBounds: realBounds toReducedBounds: claimedBounds]; [map setRegion:reducedRegion animated:YES]; } + (MKCoordinateRegion) sliceRegion: (MKCoordinateRegion) bigRegion inBounds: (CGRect) wholeBounds toReducedBounds: (CGRect) reducedBounds { MKCoordinateRegion reducedRegion; // Coords of our region corners in lat/long CLLocationDegrees left = bigRegion.center.longitude - bigRegion.span.longitudeDelta/2.0; CLLocationDegrees right = bigRegion.center.longitude + bigRegion.span.longitudeDelta/2.0; CLLocationDegrees top = bigRegion.center.latitude + bigRegion.span.latitudeDelta/2.0; CLLocationDegrees bottom = bigRegion.center.latitude - bigRegion.span.latitudeDelta/2.0; // Coords of our bounds in pixels CGFloat wholeLeft = wholeBounds.origin.x; CGFloat wholeRight = wholeBounds.origin.x + wholeBounds.size.width; CGFloat wholeTop = wholeBounds.origin.y; CGFloat wholeBottom = wholeBounds.origin.y + wholeBounds.size.height; // Coords of the smaller bounds in pixels CGFloat reducedLeft = reducedBounds.origin.x; CGFloat reducedRight = reducedBounds.origin.x + reducedBounds.size.width; CGFloat reducedTop = reducedBounds.origin.y; CGFloat reducedBottom = reducedBounds.origin.y + reducedBounds.size.height; // Now work out what the lat & long values for the corners of the reduced bounds are CLLocationDegrees newLeft = left + (right-left) * (reducedLeft - wholeLeft) / (wholeRight - wholeLeft); CLLocationDegrees newRight = left + (right-left) * (reducedRight - wholeLeft) / (wholeRight - wholeLeft); CLLocationDegrees newTop = top + (bottom - top) * (reducedTop - wholeTop) / (wholeBottom - wholeTop); CLLocationDegrees newBottom = top + (bottom - top) * (reducedBottom - wholeTop) / (wholeBottom - wholeTop); reducedRegion.center.longitude = (newRight + newLeft) / 2.0; reducedRegion.center.latitude = (newBottom + newTop) / 2.0; reducedRegion.span.longitudeDelta = newRight - newLeft; reducedRegion.span.latitudeDelta = newTop - newBottom; return reducedRegion; } +(MKCoordinateRegion)getMapRegion: (MKMapView*) map { CGRect bounds = map.bounds; MKCoordinateRegion region = [map convertRect:bounds toRegionFromView:map]; // the region we can see on the screen, not the map wonky region! if ((region.span.latitudeDelta < 0.0) || (region.span.longitudeDelta < 0.0) || region.span.longitudeDelta / region.span.latitudeDelta > 5.0 || region.span.latitudeDelta / region.span.longitudeDelta > 5.0 ) { LogD(@"getMap: region: bad span - lat: %f, long: %f", region.span.latitudeDelta, region.span.longitudeDelta); } return region; } +(void)setMap: (MKMapView*) map center: (CLLocationCoordinate2D) center { CGRect bounds = map.bounds; MKCoordinateRegion boundsRegion = [map convertRect:bounds toRegionFromView:map]; // the region we can see on the screen MKCoordinateRegion claimedRegion = map.region; // the map claimed region, which is wonkily different after a rotate in ios7 CLLocationCoordinate2D offsetCenter; // make up a value to tell the map to center on which will make it really center offsetCenter.latitude = center.latitude - ( boundsRegion.center.latitude - claimedRegion.center.latitude ); offsetCenter.longitude = center.longitude - ( boundsRegion.center.longitude - claimedRegion.center.longitude ); [map setCenterCoordinate:offsetCenter animated:YES]; } +(CLLocationCoordinate2D)getMapCenter: (MKMapView*) map { CGRect bounds = map.bounds; MKCoordinateRegion boundsRegion = [map convertRect:bounds toRegionFromView:map]; // the region we can see on the screen return boundsRegion.center; } 
+4
source share
1 answer

When I set the display area on iOS 7 to LandscapeRight, everything works fine.

When I rotate the device in LandscapeLeft and load the same region, the map shifts on a wide scale and approaches the far. The zoom level must be multiplied by 100 to fix the problem, i.e. 50,000 becomes 5,000,000, and I need to subtract 23 from the lat and add 3 to the bosom, i.e. (41.0, 29.0) becomes (18.0, 32.0).

After some testing, I can fix such a problem for iOS 7 and iOS 6 (sorry, the iOS version checks it quickly and dirty)

 if([[[UIDevice currentDevice] systemVersion] rangeOfString:@"7."].location != NSNotFound){ if(self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft){ CLLocationCoordinate2D startCoord = CLLocationCoordinate2DMake(41.0, 29.0); [_mapView setRegion:MKCoordinateRegionMakeWithDistance(startCoord, 5000000.0, 5000000.0) animated:NO]; }else if(self.interfaceOrientation == UIInterfaceOrientationLandscapeRight){ CLLocationCoordinate2D startCoord = CLLocationCoordinate2DMake(18.0, 32.0); [_mapView setRegion:MKCoordinateRegionMakeWithDistance(startCoord, 50000.0, 50000.0) animated:NO]; } }else{ MKCoordinateRegion region; region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.3; region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.7; region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * span; // Add a little extra space on the sides region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * span; // Add a little extra space on the sides region = [_mapView regionThatFits:region]; [_mapView setRegion:region animated:NO]; } 
0
source

All Articles