views:

432

answers:

1

I'm working on some iPhone MapKit code which fires off some events when the boundaries of the map change (basically some queries to an external server). There is one edge case I can't seem to solve. When users enter a new address I use setRegion to zoom in on that location and afterwards I compute the bounds of the map and query my external server with those coordinates. I always call setRegion however, there is one edge case when it will not fire. That, is, when a user magically happens to select the exact same address that lies at the current center of the map, when that map is zoomed to exactly the same region. Of course this possibility is rare but it is easy achievable with the following code:

CLLocation *centerOfMap = [[CLLocation alloc] initWithLatitude:mapView.centerCoordinate.latitude longitude:mapView.centerCoordinate.longitude];
mySearchLocation.searchLocation = centerOfMap;

//Recenter and zoom map in on search location
MKCoordinateRegion region =  {{0.0f, 0.0f}, {0.0f, 0.0f}};
region.center = mySearchLocation.searchLocation.coordinate;region.span.longitudeDelta = 0.01f;
region.span.latitudeDelta = 0.01f;
[self.mapView setRegion:region animated:YES];

This would be the equivalent of allowing the user to drop a pin at the center of the current map and fire off a query to my server based on that. Unfortunately because the code logic depends on the region changing (which I've done so that users can easily pan around the map and not have to explicitly press a refresh button), I need a work around. How can I know when setRegion has been called but it won't fire regionWillChange / regionDidChange. Can I override the function some how?

EDIT: As I commented on the first answer, I tried to detect when the region wouldn't change by using the following code:

//Recenter and zoom map in on search location
MKCoordinateRegion region =  {{0.0f, 0.0f}, {0.0f, 0.0f}};
region.center = mySearchLocation.searchLocation.coordinate;
region.span.longitudeDelta = 0.01f;
region.span.latitudeDelta = 0.01f;
region = [mapView regionThatFits:region]; //Not sure if this is necessary

NSLog(@"diff in latitude of center %f", (mapView.region.center.latitude - region.center.latitude));
NSLog(@"diff in longitude of center %f", (mapView.region.center.longitude - region.center.longitude));
NSLog(@"diff in latitude span %f", (mapView.region.span.latitudeDelta - region.span.latitudeDelta));
NSLog(@"diff in longitude span %f", (mapView.region.span.longitudeDelta - region.span.longitudeDelta));

[self.mapView setRegion:region animated:YES];

Unfortunately when I set the searchLocation to be the center of the current map I get the following results:

diff in latitude of center 0.000000
diff in longitude of center 0.000016
diff in latitude span -0.000000
diff in longitude span 0.000000

In different cases the error is slightly different but generally speaking even when the region is slightly different like this setRegion or morever, regionDidChange, do not fire. Can anyone explain why? Or how I could go about detecting this properly. Note: I also tried with mapView.centerCoordinate but I get similar errors, and I only want to know when the region will NOT change (if the centerCoordinate is the same the zoom level / region can still be different).

A: 

Why don't you just call regionWill/Did change manually from the code that is setting the new map location if it detects the point it would set the map to would be the current center?

Kendall Helmstetter Gelner
That is exactly what I thought to do but there is a weird unexplained margin of error so they are never exactly equal. I then moved on to try to detect (myself) when the region would change (before calling setRegion) and despite the same bizarre margin of error (meaning the regions are not identical) setRegion does not fire. I will edit the original post with the code. More ideas appreciated!
deadroxy
Anyone have any other suggestions or should I be submitting a bug to Apple?
deadroxy
Sorry, didn't see your other comment - I think you should file a bug on that (hint, Apple will ask for a sample project so you might as well build one now). However a workaround would be detecting you are setting the center to a new center that is within some margin of error, and call your callbacks yourself... you can subclass MKMapView to override setCenter and do the detection there before you call super.setCenter.
Kendall Helmstetter Gelner
The problem is not so much coding that up (I tried something similar, but with the region instead of the center) - the problem is I don't actually know the margin of error. So it's possible that sometimes setRegion will fire and other times not, but I have no way of knowing how the Apple code calculates when to fire so I am basically just guessing and possibly introducing weird bugs. But yes, I think it's time to talk to Apple :D Thanks again!
deadroxy