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.
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.
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];
}
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;
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.
Essaye ça:
[mapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
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