web-dev-qa-db-fra.com

Comment définir la précision et le filtre de distance lors de l'utilisation de MKMapView

Lorsque j'utilise setShowsUserLocation avec MKMapView pour suivre l'emplacement de l'utilisateur, comment définir le filtre de précision et de distance? Je ne parle pas de CLLocationManager.

Merci,

29
Van Du Tran

Vous ne pouvez pas contrôler la précision du gestionnaire d'emplacement interne MKMapView (celui utilisé pour suivre l'utilisateur avec le point bleu), mais vous pouvez créer le vôtre et l'utiliser pour recentrer la carte. Voici une recette ...

Pour gérer les autorisations d'emplacement principal

Dans le délégué de l'emplacement central:

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
    if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied){
        NSLog(@"User has denied location services");
    } else {
        NSLog(@"Location manager did fail with error: %@", error.localizedFailureReason);
    }
}

Juste avant de configurer le gestionnaire d'emplacement:

if (![CLLocationManager locationServicesEnabled]){
    NSLog(@"location services are disabled"];
    return;
}
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied){
    NSLog(@"location services are blocked by the user");
    return;
}
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorized){
    NSLog(@"location services are enabled");
}  
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined){
    NSLog(@"about to show a dialog requesting permission");
}

Pour configurer l'emplacement principal

self.locationManager = [CLLocationManager new];
self.locationManager.purpose = @"Tracking your movements on the map.";
self.locationManager.delegate = self;

/* Pinpoint our location with the following accuracy:
 *
 *     kCLLocationAccuracyBestForNavigation  highest + sensor data
 *     kCLLocationAccuracyBest               highest     
 *     kCLLocationAccuracyNearestTenMeters   10 meters   
 *     kCLLocationAccuracyHundredMeters      100 meters
 *     kCLLocationAccuracyKilometer          1000 meters 
 *     kCLLocationAccuracyThreeKilometers    3000 meters
 */
self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;

/* Notify changes when device has moved x meters.
 * Default value is kCLDistanceFilterNone: all movements are reported.
 */
self.locationManager.distanceFilter = 10.0f;

/* Notify heading changes when heading is > 5.
 * Default value is kCLHeadingFilterNone: all movements are reported.
 */
self.locationManager.headingFilter = 5;

// update location
if ([CLLocationManager locationServicesEnabled]){
    [self.locationManager startUpdatingLocation];
}

Pour recentrer la carte avec notre gestionnaire de localisation

- (void)locationManager:(CLLocationManager *)manager 
    didUpdateToLocation:(CLLocation *)newLocation 
           fromLocation:(CLLocation *)oldLocation 
{
    MKCoordinateRegion region = { { 0.0f, 0.0f }, { 0.0f, 0.0f } };
    region.center = newLocation.coordinate;
    region.span.longitudeDelta = 0.15f; 
    region.span.latitudeDelta = 0.15f;
    [self.mapView setRegion:region animated:YES];
}

Mettez cela sur le délégué. MKMapView n'a pas de filtre de distance ou de précision, seul CLLocationManager en a. Ce que MKMapView a est une étendue de région autour d'un point, dans l'exemple ci-dessus 0,15 degrés (0,15 * 111 Km).

Choses que j'ai essayées et qui n'ont pas fonctionné

La documentation ne dit pas d'où MKMapView obtient ses mises à jour. j'ai essayé

- (void)locationManager:(CLLocationManager *)manager 
    didUpdateToLocation:(CLLocation *)newLocation 
           fromLocation:(CLLocation *)oldLocation {
    NSLog(@"newLocation %@", newLocation.timestamp);
    NSLog(@"last map location %@", [NSString stringWithFormat:@"%@",[[[self.mapView userLocation] location] timestamp]]);
}

et je reçois des valeurs différentes sur chacun. Il semble que MKMapView utilise son propre CLLocationManager, ce qui signifie que vous ne pouvez pas définir sa précision. Vous ne pouvez pas non plus ajouter votre délégué pour le CLLocationManager du MKMapView.

Mon impression est que la seule façon de définir la précision est de définir la position de l'utilisateur sur NON et de créer une annotation personnalisée avec un point bleu, ce qui signifie recentrer la carte manuellement telle que publiée. Vous pouvez obtenir le graphique à points bleus à partir du SDK avec l'extracteur d'illustrations du projet github.

Je ne sais pas si je manque quelque chose ou si cette partie de MKMapView est juste nul.

81
Jano

Pour afficher la carte, voici un exemple de code.

Importez d'abord MKMapKit et CoreLocation Framework dans votre fichier .h.

#import <MapKit/MapKit.h>
 #import <CoreLocation/CoreLocation.h>

Ajouter MKMapKit et CoreLocation Delegate dans un fichier .h

@interface MapViewController : UIViewController <MKMapViewDelegate, CLLocationManagerDelegate>


CGPoint gameMapCenter = CGPointMake([[UIScreen mainScreen] bounds].size.width / 2, [[UIScreen mainScreen] bounds].size.height / 2);
    gameMapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, 640, 620)];
    [gameMapView setCenter:gameMapCenter];
    [gameMapView setMapType:MKMapTypeStandard];
    [gameMapView setDelegate:self];
    [self.view addSubview:gameMapView];
    [gameMapView setShowsUserLocation:YES];

Utilisez CLLocationManager pour récupérer l'emplacement de l'utilisateur.

Déclarez une instance de CLLocationManager

CLLocationManager *locationManager;

Dans ViewDidLoad

locationManager = [[CLLocationManager alloc] init];

[locationManager setDelegate:self];

[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];

[locationManager setDistanceFilter:kCLDistanceFilterNone];

[locationManger startUpdatingLocation];

startUpdatingLocation Implémentation de la méthode:

(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation 
{
      //Your Stuff
}
3
morroko

Vous ne pouvez pas définir la précision, cependant, vous pouvez obtenir la précision via userLocation dans la méthode déléguée MKMapView.

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
    NSLog(@"%f", userLocation.location.horizontalAccuracy);
}
2
nonamelive