web-dev-qa-db-fra.com

Comment zoomer un MKMapView à l'emplacement actuel de l'utilisateur sans CLLocationManager?

Avec le MKMapView, il y a une option appelée "Afficher l'emplacement actuel des utilisateurs" qui affichera automatiquement un emplacement des utilisateurs sur le map.

Je voudrais déplacer et zoomer sur cet emplacement lorsqu'il est trouvé (et s'il change).

Le problème est qu'il ne semble pas y avoir de méthode appelée lorsque l'emplacement de l'utilisateur est mis à jour sur le map, donc je n'ai nulle part où mettre le code qui va zoom/scroll.

Existe-t-il un moyen d'être averti lorsqu'un MKMapView a (ou a mis à jour) l'emplacement de l'utilisateur afin que je puisse le déplacer/zoomer dessus? Si j'utilise mon propre CLLocationManager les mises à jour que je reçois ne correspondent pas aux mises à jour du marqueur utilisateur sur la carte, donc ça a l'air idiot quand ma carte bouge et zoome quelques secondes avant que l'épingle bleue n'apparaisse.

Cela ressemble à une fonctionnalité de base, mais j'ai passé des semaines à chercher une solution et je n'ai rien trouvé de proche.

70
Danny Tuppeny

Vous devez vous inscrire aux notifications KVO de userLocation.location propriété de MKMapView.

Pour ce faire, mettez ce code dans viewDidLoad: de votre ViewController ou n'importe où à l'endroit où votre vue de carte est initialisée.

[self.mapView.userLocation addObserver:self  
        forKeyPath:@"location"  
           options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld)  
           context:NULL];

Ensuite, implémentez cette méthode pour recevoir les notifications KVO

- (void)observeValueForKeyPath:(NSString *)keyPath  
                      ofObject:(id)object  
                        change:(NSDictionary *)change  
                       context:(void *)context {  

    if ([self.mapView showsUserLocation]) {  
        [self moveOrZoomOrAnythingElse];
        // and of course you can use here old and new location values
    }
}

Ce code fonctionne bien pour moi.
BTW, self est mon ViewController dans ce contexte.

106
ddnv

Ceci est une combinaison de ddnv et de la réponse de Dustin qui a fonctionné pour moi:

mapView est le nom de MKMapView * mapView;

Dans le viewDidLoad ajoutez cette ligne, notez qu'il pourrait y avoir plus de lignes dans la charge. C'est simplement simplifié.

- (void) viewDidLoad
{
    [self.mapView.userLocation addObserver:self 
                                forKeyPath:@"location" 
                                   options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld) 
                                   context:nil];
}

Créez ensuite la méthode de référencement réelle qui déplace la carte vers l'emplacement actuel:

// Listen to change in the userLocation
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{       
    MKCoordinateRegion region;
    region.center = self.mapView.userLocation.coordinate;  

    MKCoordinateSpan span; 
    span.latitudeDelta  = 1; // Change these values to change the zoom
    span.longitudeDelta = 1; 
    region.span = span;

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

N'oubliez pas de désallouer correctement et de désinscrire l'observateur:

- (void)dealloc 
{
    [self.mapView.userLocation removeObserver:self forKeyPath:@"location"];
    [self.mapView removeFromSuperview]; // release crashes app
    self.mapView = nil;
    [super dealloc];
}
52
MrHus

Depuis iOS 5.0 Apple a ajouté une nouvelle méthode à MKMapView. Cette méthode fait exactement ce que vous voulez et plus encore.

Jetez un œil à: https://developer.Apple.com/documentation/mapkit/mkmapview

- (void)setUserTrackingMode:(MKUserTrackingMode)mode animated:(BOOL)animated;
45
thijsai

Vous pouvez surveiller quand le MKMapView met à jour l'emplacement de l'utilisateur sur la carte en implémentant le protocole MKMapViewDelegate. Il suffit de mettre en œuvre:

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation      {
    CLLocationAccuracy accuracy = userLocation.location.horizontalAccuracy;
    if (accuracy ......) {
    } 
}

Ce rappel doit être parfaitement synchronisé avec ce qui est affiché sur la carte.

13
yonel

Essaye ça:

[mapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
6
Kenan Karakecili

Pas de problème ... Dans la méthode viewDidLoad de votre sous-classe UIViewController qui a le MKMapView ajoutez ceci (en supposant que votre MKMapView est nommé map):

CLLocation *location = [[[CLLocation alloc] initWithLatitude:map.centerCoordinate.latitude longitude:map.centerCoordinate.longitude] autorelease]; //Get your location and create a CLLocation
MKCoordinateRegion region; //create a region.  No this is not a pointer
region.center = location.coordinate;  // set the region center to your current location
MKCoordinateSpan span; // create a range of your view
span.latitudeDelta = BASE_RADIUS / 3;  // span dimensions.  I have BASE_RADIUS defined as 0.0144927536 which is equivalent to 1 mile
span.longitudeDelta = BASE_RADIUS / 3;  // span dimensions
region.span = span; // Set the region's span to the new span.
[map setRegion:region animated:YES]; // to set the map to the newly created region
1