regionThatFits doubles span area - iphone

I'm working on component using MKMapView. Map should double zoom on annotation tap. To do this, I try to reduce twice map region span, but sometimes it works incorrectly:
Here peace of code:
MKCoordinateSpan newSpan = mapView.region.span;
NSLog(#"old: %f, %f", newSpan.latitudeDelta, newSpan.longitudeDelta);
newSpan = MKCoordinateSpanMake(newSpan.latitudeDelta / 2.0, newSpan.longitudeDelta / 2.0);
NSLog(#"new: %f, %f", newSpan.latitudeDelta, newSpan.longitudeDelta);
MKCoordinateRegion region = [mapView regionThatFits:MKCoordinateRegionMake(centerCoordinate, newSpan)];
NSLog(#"!!!! (%f, %f) (%f, %f)", region.center.latitude, region.center.longitude, region.span.latitudeDelta, region.span.longitudeDelta);
I take current span, reduce it and pass to regionThatFits. Sometimes results are:
old: 0.609257, 0.914612
new: 0.304629, 0.457306
!!!! (55.805472, 37.579371) (0.608178, 0.914612)
regionThatFits doubles span passed to it. So visual effect is centering of view annotation without zooming.
Any suggestions?

I had the same problem, and it happen to be that I was sometimes changing the mapView size (for the needs of the application). Then I was using regionThatFits on my mapView when its height was 0.
As FKDev answer says, regionThatFits recalculates the span according to the mapView actual frame (what was causing the crash). Hope that can help someone.

You shouldn't use regionThatFits: because it is used to change the span value to match the view frame.
From Apple's Doc :
A region that is still centered on the same point of the map but whose span values are adjusted to fit in the map view’s frame.
In your case, you can just change the span value of the map region directly.
[mapView setRegion:MKCoordinateRegionMake(centerCoordinate, newSpan)];

Related

MapKit iPhone display Zoom Controls

Is it possible using MapKit to show a map in iPhone, like i´m doing, to display zoom controls on the map?
If not, what are the flags or methods i should use to increase and diminish the zoom, so i can created methods which will do this at the push of a button.
There aren't any built-in controls for it.
A couple of suggestions:
You can predefine some spans and store them in an array somewhere and then store your position in that array as well. Zooming in/out changes the position and gets the span.
Zooming in takes the current span and divides by 2, zooming out multiplies by 2.
You change the span in the region of the mapView. So you have to:
Get the region of the mapView.
Get the span of the region.
Change the span to what you want.
Set the regions span to the new span.
Set the mapView's region to the new region.
Here's some code for suggestion 2:
MKCoordinateRegion region = mapView.region;
MKCoordinateSpan span;
span.latitudeDelta = region.span.latitudeDelta*2;
span.longitudeDelta = region.span.longitudeDelta*2;
region.span = span;
[mapView setRegion:region animated:TRUE];
For swift 4, this is what I use:
func zoom(_ zoomin : Bool) {
var region = mapView.region;
var span = MKCoordinateSpan();
span.latitudeDelta = zoomin ? region.span.latitudeDelta / 2 : region.span.latitudeDelta * 2;
span.longitudeDelta = zoomin ? region.span.longitudeDelta / 2 : region.span.longitudeDelta * 2;
region.span = span;
mapView.setRegion(region, animated: true);
}
Off the top of my head I don't remember (at work on a windows box) if there is a switch to display the zoom controls. I assume you are talking about displaying the level of zoom, because by default you can pinch/spread the view for zoom.
If there isn't a switch to display the controls, then you will need to create a custom view layer and put it on top of the mapkit view. Then you will need to call the different functions to change the zoom level.
Those functions are all documented in the mapkit docs. Just do a search for MapKit in the documentation center.
Edit:
http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKMapView_Class/MKMapView/MKMapView.html#//apple_ref/doc/uid/TP40008205
According to the docs there isn't a switch to display the controls, but the zoom enabled property lets you turn the ability on and off.
So you can subscribe to the delegate function regionWillChange and use the mapView object to get the zoom level and then set your graphics accordingly.
I don't think you should do that, the expected way to zoom in and out is using the pinch gestures. However if you still want to go ahead and do it, you should place yourself the buttons over the MKMapView, and then with those modify the region property of the MKMapView

Invalid MKMapView region in iOS 5

MKMapView returns an invalid region under iOS 5 -- latitude + latitudeDelta/2 is over 100 and shouldn't be over 90.
Has anyone seen this problem?
Steps to Reproduce:
Create an MKMapView
Log the mapView.region from within the regionDidChangeAnimated delegate method
Zoom out the map as far as possible and drag it to the right, so the view is scrolled to the top/left
Expected Results:
In iOS 4, the mapView.region is reasonable:
lat=2.202047 lon=-67.500000 latDelta=165.698164 lonDelta=225.000000
In iOS 5, however, the mapView.region is out of bounds:
lat=17.978733 lon=-67.500000 latDelta=165.698164 lonDelta=225.000000
Latitudes should be within the -90 to 90 range. However, in iOS 5, lat + latDelta/2 is 100.827815. That is not possible. While I can clamp the values at +/- 90, the offset difference is causing problems with our overlays.
Regression:
Does not happen in iOS 4.3. Happens regularly in iOS 5. Screen dumps of the map views look identical even though the center latitude is 15 degrees off.
Notes:
Project file and screen dumps can be downloaded here.
This seems to be an adequate workaround. Rather than reading the mapView.region property, call this method instead:
#implementation MKMapView(fixedRegion)
-(MKCoordinateRegion) fixedRegion_
{
// this call is broken on iOS 5, as is the region property, so don't use them
// return( [self convertRect:self.bounds toRegionFromView:self] );
CLLocationCoordinate2D topLeft = [self convertPoint:CGPointZero toCoordinateFromView:self];
CLLocationCoordinate2D bottomRight = [self convertPoint:CGPointMake(self.bounds.size.width, self.bounds.size.height) toCoordinateFromView:self];
MKCoordinateRegion region;
region.center.latitude = (topLeft.latitude + bottomRight.latitude)/2;
region.center.longitude = (topLeft.longitude + bottomRight.longitude)/2;
region.span.latitudeDelta = fabs( topLeft.latitude - bottomRight.latitude );
region.span.longitudeDelta = fabs( topLeft.longitude - bottomRight.longitude );
return region;
}
#end
Now one could argue (correctly!) that this code isn't 100% correct either because the center value of a Mercator projection in lon/lat isn't really halfway between the top and bottom, but since this matches iOS 4 functionality and keeps the values within the legal range for the map, it works for me.
By using the MKMapView+ZoomLevel category, you won’t have to bother setting the region at all.
here is very good tutorial on the same
http://troybrant.net/blog/2010/01/set-the-zoom-level-of-an-mkmapview/
or
http://mayurbirari.wordpress.com/2011/02/07/how-to-access-mkmapkit-in-iphone/
After you perform the zoom/pinch operation try to load the region in
-(void) mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
instead in
regionDidChangeAnimated.
hope this will help..:)

MKCoordinateregion's center changes when span changed - iphone

I have a MKCoordinateregion called region. I want to change span of this region without changing it's center. I am using following method to change zoom.
-(void) changeZoom
{
NSLog(#"before zoom span, center are %f, %f,%f,%f", region.span.latitudeDelta, region.span.longitudeDelta, mymap.centerCoordinate.latitude, mymap.centerCoordinate.longitude);
region.span.latitudeDelta = current_factor ;
region.span.longitudeDelta = current_factor ;
region.center.latitude = mymap.centerCoordinate.latitude ;
region.center.longitude = mymap.centerCoordinate.longitude ;
[mymap setRegion:region animated:TRUE];
NSLog(#"after zoom span, center are %f, %f,%f,%f", region.span.latitudeDelta, region.span.longitudeDelta, mymap.centerCoordinate.latitude, mymap.centerCoordinate.longitude);
}
Log shows :
before zoom span, center are 0.021950, 0.021950,19.068080,72.838111
after zoom span, center are 0.043901, 0.043901,19.068040,72.838154
This method set's span accurately as desired.But I dont want any change in the center's coordinate, Because when I zoom out and then zoom back I end up at a location different from starting location.
Is there any method so that zoom in and out are possible without any change in center?
Thanks for any help in advance.
Your before and after center coordinates are almost exactly the same, so it shouldn't be a problem. If you really want the exact same center coordinates, call setCenterCoordinate:animated: right after you use setRegion:animated: and pass some saved center coordinates.
CLLocationCoordinate2D originalCenter = mymap.centerCoordinate;
// ... adjust region
[mymap setCenterCoordinate:originalCenter animated:NO];
Also, you should use YES instead of TRUE for booleans:
[mymap setRegion:region animated:YES];
You need to adjust the region of the map to make sure the aspect ratio fits the frame size of the map view.
Once the region with the desired center is calculated, adjust the region as,
MKCoordinateRegion adjustedRegion = [mymap regionThatFits:region];
[mymap setRegion:adjustedRegion animated:TRUE];
See docs.

Move MKMapView point to pixel coordinates

I have a quick question. I am using a custom view as a callout accessory for my map view. I am having some issues with getting the annotation to move to the right bottom corner of the said view. I am currently trying to get the CGPoint coords of the selected annotation, but beyond that I've drawn a blank Any help would be greatly appreciated.
The current code I'm using (I know it is incorrect is:)
CGPoint bottomLeftPoint = CGPointMake(xOffset,[self.internalAnnotationCallout view].frame.size.height);
CLLocationCoordinate2D bottomLeftCoord = [self.branchLocation convertPoint:bottomLeftPoint toCoordinateFromView:self.branchLocation];
MKCoordinateSpan span = {latitudeDelta: kMapMultiLatDelta, longitudeDelta: kMapMultiLatDelta};
MKCoordinateRegion region = {bottomLeftCoord, span};
[self.branchLocation setRegion:region animated:YES];
//[self.branchLocation setCenterCoordinate:newCenterCoordinate animated:YES];
EDIT:
Ok so I messed around with this a little and was able to to put something together that seems to work, hoping that I now actually understand what you're trying to achieve!
- (void)shiftToCorner{
//ignore "Annotation", this is just my own custom MKAnnotation subclass
Annotation *currentAnnotation = [[mapView selectedAnnotations] objectAtIndex:0];
[mapView setCenterCoordinate:currentAnnotation.coordinate];
CGPoint fakecenter = CGPointMake(20, 20);
CLLocationCoordinate2D coordinate = [mapView convertPoint:fakecenter toCoordinateFromView:mapView];
[mapView setCenterCoordinate:coordinate animated:YES];
}
Let me quickly explain what this does; Let's say you want your annotation to move to a position 20 points in from the right edge and 20 points up from the bottom edge of the map view. If you think about it, if the current annotation is at the center of the map view, then the distance to this point is the same as the distance to (20, 20). This means that we can send our annotation to this point by first centering our map view on the annotation, then animating to (20, 20).

MKMapView's visibleMapRect property does not set map area correctly?

I am using the visibleMapRect property of MKMapView to set the bounds of the visible area in my app. But for some reason, the MKMapRect value of the map is different
//setting the bounds
MKMapRect bounds = MKMapRectMake(x, y, width, height);
[map setVisibleMapRect:bounds];
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{
MKMapRect mpRect = [mapView visibleMapRect];
NSLog(#"Origin: %f, %f", mpRect.origin.x, mpRect.origin.y);
NSLog(#"Size: %f, %f", mpRect.size.width, mpRect.size.height);
}
The value printed by the mapView:regionDidChangeAnimated: method is different from what I had set.
How do I change this and ensure what I set as the visibleRect is what really is visible?
Thanks.
I would imagine that this is because the aspect ratio of your MKMapView is different from the ratio of your MKMapRect but without further information it's hard to tell.
Could you provide logs of the MapRect you are trying to set and the one that is getting returned?