Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting when a user scrolls MKMapView a certain distance?

Tags:

iphone

mapkit

I want to determine if a user has scrolled more than a certain percentage of the map then disable centering of the map from the user location (similar to how the Maps app works).

I'm not sure which methods to make use of.

I think it would be straightforward to create a rectangle and see if the rectangle contains the current center point, however I have to target IOS 3, so I can't make use of many of the newer Mapkit apis.

I've tried futzing with CLLocation, and using distanceFrom, between the current mapcenter, and the users location, but I'm trying to figure out if that distance is a certain percentage.

like image 908
Alan Avatar asked Mar 29 '11 06:03

Alan


1 Answers

I personally find it more helpful when someone can post a snippet of code versus general prose about how one might go about this. Here's what I came up with- roughly hacked out to simply better answer this question:

In a header file I have:

#define SCROLL_UPDATE_DISTANCE          80.00

and in my view (that is both a delegate for CLLocationManagerDelegate, MKMapViewDelegate):

// this method is called when the map region changes as a delegate of MKMapViewDelegate
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
    NSLog(@"regionDidChangeAnimated");
    MKCoordinateRegion mapRegion;   
    // set the center of the map region to the now updated map view center
    mapRegion.center = mapView.centerCoordinate;

    mapRegion.span.latitudeDelta = 0.3; // you likely don't need these... just kinda hacked this out
    mapRegion.span.longitudeDelta = 0.3;

    // get the lat & lng of the map region
    double lat = mapRegion.center.latitude;
    double lng = mapRegion.center.longitude;

    // note: I have a variable I have saved called lastLocationCoordinate. It is of type
    // CLLocationCoordinate2D and I initially set it in the didUpdateUserLocation
    // delegate method. I also update it again when this function is called
    // so I always have the last mapRegion center point to compare the present one with 
    CLLocation *before = [[CLLocation alloc] initWithLatitude:lastLocationCoordinate.latitude longitude:lastLocationCoordinate.longitude];
    CLLocation *now = [[CLLocation alloc] initWithLatitude:lat longitude:lng];

    CLLocationDistance distance = ([before distanceFromLocation:now]) * 0.000621371192;
    [before release];
    [now release];

    NSLog(@"Scrolled distance: %@", [NSString stringWithFormat:@"%.02f", distance]);

    if( distance > SCROLL_UPDATE_DISTANCE )
    {
        // do something awesome
    }

    // resave the last location center for the next map move event
    lastLocationCoordinate.latitude = mapRegion.center.latitude;
    lastLocationCoordinate.longitude = mapRegion.center.longitude;

}

Hope that sends you in the right direction.

distanceFromLocation is iOS 3.2 and later. initWithLatitude is iOS 2.0 and later. MKCoordinateRegion is iOS 3.0 and later. MKMapView centerCoordinate is iOS 3.0 and later.

Also- please feel free to jump in and set me straight where I've erred. I'm figuring all of this out myself- but this is working fairly well for me so far.

Hope this helps someone.

like image 163
Michael Reed Avatar answered Sep 29 '22 12:09

Michael Reed