web-dev-qa-db-fra.com

Le kit de cartes iOS 8 Obj-C ne peut pas obtenir l'emplacement des utilisateurs

Je travaille avec Map Kit sous iOS 8 avec Obj-C NOT Swift. Je ne parviens pas à obtenir l'emplacement de l'appareil; il est défini sur 0.00, 0.00 et j'obtiens l'erreur suivante:

Trying to start MapKit location updates without prompting for location authorization. Must call -[CLLocationManager requestWhenInUseAuthorization] or -[CLLocationManager requestAlwaysAuthorization] first.

J'ai implémenté: (j'ai essayé un à la fois et pas de chance)

if(IS_OS_8_OR_LATER) {
    [self.locationManager requestWhenInUseAuthorization];
    [self.locationManager requestAlwaysAuthorization];
}
[self.locationManager startUpdatingLocation]; 

Et dans info.plist

NSLocationWhenInUseUsageDescription  :   App would like to use your location.
NSLocationAlwaysUsageDescription  :  App would like to use your location.

Je suis invité à autoriser l'application à utiliser ma position, mais une fois que je suis d'accord, rien ne change. L'emplacement est indiqué comme étant 0.00, 0.00.

Code pour afficher l'emplacement des utilisateurs:

//Get Location
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];

MKCoordinateRegion region = { { 0.0, 0.0 }, { 0.0, 0.0 } };
region.center.latitude = self.locationManager.location.coordinate.latitude;
region.center.longitude = self.locationManager.location.coordinate.longitude;
region.span.longitudeDelta = 0.005f;
region.span.longitudeDelta = 0.005f;
[mapView setRegion:region animated:YES];

Mike.

** EDIT: Voir la réponse ci-dessous.

51
MBarton

Je l'ai fait travailler. J'ai posté mon code ci-dessous pour aider quiconque ayant des problèmes.

Voici mon code complet pour que la vue Carte de MapKit fonctionne dans iOS 8.

Dans votre AppName - Info.plist Ajoutez une nouvelle ligne avec le nom de la clé étant:

NSLocationWhenInUseUsageDescription

Ou

NSLocationAlwaysUsageDescription

La valeur étant une chaîne du message que vous souhaitez afficher:

YourAppName would like to use your location.

Dans votre fichier d'en-tête. (J'utilise Nom de l'application - Prefix.pch mais YourViewController.h fonctionnera aussi)

#define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)

YourViewController.h

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

@interface YourViewController : UIViewController <MKMapViewDelegate,  CLLocationManagerDelegate> {

}


@property(nonatomic, retain) IBOutlet MKMapView *mapView;
@property(nonatomic, retain) CLLocationManager *locationManager;

YourViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.


    mapView.delegate = self;
    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;
    #ifdef __IPHONE_8_0
    if(IS_OS_8_OR_LATER) {
         // Use one or the other, not both. Depending on what you put in info.plist
        [self.locationManager requestWhenInUseAuthorization];
        [self.locationManager requestAlwaysAuthorization];
    }
    #endif
    [self.locationManager startUpdatingLocation];

    mapView.showsUserLocation = YES;
    [mapView setMapType:MKMapTypeStandard];
    [mapView setZoomEnabled:YES];
    [mapView setScrollEnabled:YES];
}

-(void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:YES];

    self.locationManager.distanceFilter = kCLDistanceFilterNone;
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    [self.locationManager startUpdatingLocation];
    NSLog(@"%@", [self deviceLocation]);

    //View Area
    MKCoordinateRegion region = { { 0.0, 0.0 }, { 0.0, 0.0 } };
    region.center.latitude = self.locationManager.location.coordinate.latitude;
    region.center.longitude = self.locationManager.location.coordinate.longitude;
    region.span.longitudeDelta = 0.005f;
    region.span.longitudeDelta = 0.005f;
    [mapView setRegion:region animated:YES];

}

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
    MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
    [self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
}
- (NSString *)deviceLocation {
    return [NSString stringWithFormat:@"latitude: %f longitude: %f", self.locationManager.location.coordinate.latitude, self.locationManager.location.coordinate.longitude];
}
- (NSString *)deviceLat {
    return [NSString stringWithFormat:@"%f", self.locationManager.location.coordinate.latitude];
}
- (NSString *)deviceLon {
    return [NSString stringWithFormat:@"%f", self.locationManager.location.coordinate.longitude];
}
- (NSString *)deviceAlt {
    return [NSString stringWithFormat:@"%f", self.locationManager.location.altitude];
}

Prendre plaisir!

--Mike

130
MBarton

Il n'est écrit nulle part, mais si votre application démarre avec MapKit, vous recevrez toujours le message d'erreur "Essayer de démarrer les mises à jour d'emplacement MapKit sans demander l'autorisation d'emplacement", même après avoir implémenté la réponse de MBarton. Pour l'éviter, vous devez créer un nouveau contrôleur de vue avant MapKit et y implémenter les délégués du gestionnaire d'emplacement. Je l'ai appelé AuthorizationController.

Donc, dans AuthorizationController.h:

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

@interface MCIAuthorizationController : UIViewController <CLLocationManagerDelegate>

@property (strong, nonatomic) CLLocationManager *locationManager;

@end

Et dans AuthorizationController.m:

- (void)viewDidLoad {
    [super viewDidLoad];

    // Location manager
    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;

    // Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7.
    if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
        [self.locationManager requestWhenInUseAuthorization];
    }
}

#pragma mark - Location Manager delegates

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
    NSLog(@"didUpdateLocations: %@", [locations lastObject]);
}


- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
    NSLog(@"Location manager error: %@", error.localizedDescription);
}

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
    if (status == kCLAuthorizationStatusAuthorizedWhenInUse) {
        [self.locationManager startUpdatingLocation];
        [self performSegueWithIdentifier:@"startSegue" sender:self];
    } else if (status == kCLAuthorizationStatusDenied) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Location services not authorized"
                                                        message:@"This app needs you to authorize locations services to work."
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
    } else
        NSLog(@"Wrong location status");
}
8
Rodrigo Pinto

Essaye celui-là:

 (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {

    if (status == kCLAuthorizationStatusAuthorizedWhenInUse) {
        self.mapView.showsUserLocation = YES;
    }
3
brusnikin

J'ai eu le même problème mais l'ajout de ces deux lignes dans le fichier plist a résolu mes problèmes

NSLocationWhenInUseUsageDescription

Et

NSLocationAlwaysUsageDescription

REMARQUE: Doit fournir une description de chaîne de ces deux valeurs. Vous pouvez utiliser n'importe lequel d'entre eux dans votre fichier de contrôleur comme ci-dessous

self.locationManager= [[CLLocationManager alloc] init];
self.locationManager.delegate=self;
[self.locationManager requestAlwaysAuthorization];

Vous devez implémenter CLLOcationManagerDelegate dans votre contrôleur pour accéder à cette fonctionnalité.

2
Aadil Keshwani

Votre code semble correct, bien qu'il ne soit pas nécessaire d'appeler requestWhenInUseAuthorization et l'autre requestAlwaysAuthorization, choisissez celui dont vous avez besoin.

Le code pour l’affichage des localisations est en train d’attribuer locationManager, ne vous attendez pas à obtenir des données de localisation instantanément.

vous devez attendre que la méthode déléguée soit appelée: -(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
, alors self.locationManager.location sera également défini.

2
PetrV

Suite à la réponse de Mikes, j’ai trouvé que l’utilisation de à la fois [self.locationManager requestWhenInUseAuthorization]; et [self.locationManager requestAlwaysAuthorization]; comme démontré dans son code ne fonctionne pas. Vous ne devriez utiliser que UN .

Je suppose que d'autres modifications ont été apportées à une version plus récente/stable de l'API.

2
Dean Roccs

Pour étendre la réponse acceptée et si vous créez un exemple de projet avec uniquement les fonctionnalités ci-dessus, mis à part les frameworks CoreLocation et Mapkit, vous devrez peut-être ajouter UIKit, Foundation et CoreGraphics framework manuellement aussi dans Xcode 6.

0
Deepak Thakur