Usługi lokalizacyjne nie działają w systemie iOS 8


608

Moja aplikacja, która działała dobrze na iOS 7, nie działa z zestawem SDK iOS 8.

CLLocationManagernie zwraca lokalizacji i nie widzę mojej aplikacji w Ustawieniach -> Usługi lokalizacji . Przeszukałem ten problem w Google, ale nic nie wyszło. Co może być nie tak?


Możesz również użyć tego jako aplikacji referencyjnej dla rozwiązania github.com/jbanford/ConstantLocationUpdates
ashok vadivelu

19
O niektórych zmianach w menedżerze lokalizacji w iOS 8 zamieściłem
Nevan King

2
Możesz spróbować użyć tej biblioteki, która upraszcza interfejsy API Core Location i udostępnia przyjemny interfejs oparty na blokach oraz normalizuje wszystkie różnice między różnymi wersjami iOS (pełne ujawnienie: jestem autorem): github.com/lmirosevic/GBLocation
lms

Znalazłem tutaj odniesienie datacalculation.blogspot.in/2014/11/…
iOS Test

2
@nevanking You sir! potrzebuję korony! Walczę z tym problemem od czasu zmiany i jeszcze nie znalazłem „przewodnika”, jak to naprawić, to było przyjazne dla nooba. Twój przewodnik zrobił takiego idiotę jak ja, poradzę sobie z tym problemem sam. Dziękuję bardzo za ten link.
Patrick R

Odpowiedzi:


1086

Skończyłem rozwiązywanie własnego problemu.

Najwyraźniej w iOS 8 SDK requestAlwaysAuthorization(dla lokalizacji w tle) lub requestWhenInUseAuthorization(lokalizacja tylko na pierwszym planie) CLLocationManagerwymagane jest połączenie przed rozpoczęciem aktualizacji lokalizacji.

Nie musi też być NSLocationAlwaysUsageDescriptionalbo NSLocationWhenInUseUsageDescriptionkluczem Info.plistz wiadomości mają być wyświetlane w wierszu polecenia. Dodanie ich rozwiązało mój problem.

wprowadź opis zdjęcia tutaj

Mam nadzieję, że pomoże to komuś innemu.

EDYCJA: Aby uzyskać bardziej szczegółowe informacje, spójrz na: Core-Location-Manager-Changes-in-ios-8


6
czy możesz podać dokładną wartość zaktualizowaną w Info.plist? Nie widzę tego klucza w mojej Info.plist. Dodałem go i nadal nie działa. Używam Swift, iOS8 i XCode 6 beta 4
Vijay Kumar AB

4
@Vjay - musisz edytować plik Info.plist w edytorze, nie możesz ustawić tych kluczy w Xcode (od wersji beta 6).
Kendall Helmstetter Gelner

11
Przypominamy, że jeśli nie chcesz wyświetlać niestandardowego wyjaśnienia użytkownikowi, po prostu ustaw ten klucz na pusty ciąg.
niemiły

7
Musisz zachować swój menedżer lokalizacji, aby działał. więc ustaw CLLocationManager jako silną właściwość
Vassily

273
„UWIELBIAM”, że nie dostaniesz błędu, żadnego ostrzeżenia, żadnego komunikatu w dzienniku, NIC, jeśli pominiesz wpis plist. Zasadniczo Apple utworzyło wywołanie API, które NIE MA NIC, jeśli nie masz odpowiedniego wpisu plist. Dzięki @OrtwinGentz ​​za zrozumienie tego.
MobileVet

314

Wyciągałam włosy z tym samym problemem. Xcode wyświetla błąd:

Próba uruchomienia MapKitaktualizacji lokalizacji bez monitowania o autoryzację lokalizacji. Musisz zadzwonić -[CLLocationManager requestWhenInUseAuthorization]lub -[CLLocationManager requestAlwaysAuthorization]najpierw.

Ale nawet jeśli zastosujesz jedną z powyższych metod, nie wyświetli monitu, chyba że w info.plist znajduje się wpis dla NSLocationAlwaysUsageDescriptionlub NSLocationWhenInUseUsageDescription.

Dodaj następujące wiersze do info.plist, gdzie wartości ciągów reprezentują powód, dla którego musisz uzyskać dostęp do lokalizacji użytkowników

<key>NSLocationWhenInUseUsageDescription</key>
<string>This application requires location services to work</string>

<key>NSLocationAlwaysUsageDescription</key>
<string>This application requires location services to work</string>

Myślę, że tych wpisów mogło brakować, odkąd rozpocząłem ten projekt w Xcode 5. Domyślam się, że Xcode 6 może dodawać domyślne wpisy dla tych kluczy, ale nie zostały potwierdzone.

Więcej informacji na temat tych dwóch ustawień można znaleźć tutaj


13
xcode 6 domyślnie nie dodaje tych kluczy, jeśli zamierzasz zaimplementować CLLocationManager, musisz dodać je ręcznie
Wesley Smith

1
Musiałem też dodać je ręcznie, nie mogłem dodać przez widok RawValues ​​info.plist w Xcode6!
Kendall Helmstetter Gelner

1
szukałem tego na zawsze. Mój komunikat [Status autoryzacji CLLLocationManager] zwracał tylko wartość <zero>. Po dodaniu powyższych kluczy zaczął zwracać odpowiednie wyliczenia dla danych wyjściowych komunikatów. Z tego, co odkryłem, jest to znany błąd w iOS 8, ale od wieków nie mogłem znaleźć niczego w moim kontekście. Dzięki mil!
MrOli3000,

4
Podoba mi się wartość ciągu, którą wstawiłeś
Chris Chen

1
Wiadomość pojawi się jako pod-wiadomość w alercie z pytaniem, czy użytkownik chce udostępnić swoją lokalizację. Jako takie, po prostu bycie pustym (pustym) wydaje się mieć sens w mojej aplikacji. Sensowne byłoby również wyjaśnienie, dlaczego chcesz użyć lokalizacji. Jednak NSLocationWhenInUseUsageDescription nie zachowywał się zgodnie z oczekiwaniami (tj. Ciągle odmawiano zgody, mimo że zwracana wartość była poprawna). NSLocationAlwaysUsageDescription działało dobrze.
arcady bob

104

Aby upewnić się, że jest to wstecznie kompatybilne z iOS 7, powinieneś sprawdzić, czy użytkownik korzysta z iOS 8 lub iOS 7. Na przykład:

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

//In ViewDidLoad
if(IS_OS_8_OR_LATER) {
   [self.locationManager requestAlwaysAuthorization];
}

[self.locationManager startUpdatingLocation];

164
Lepszym sposobem niż sprawdzenie wersji jest sprawdzenie, czy obiekt ma ten selektor, np .: if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) { ...
progrmr

1
Miałem problem tylko z implementacją rozwiązania @ progrmr podczas budowania na Xcode 5, ponieważ nie wie on, jaka requestAlwaysAuthorizationjest metoda. Mój dodatkowy rozwiązaniem było wykorzystanie tej linii w ifrachunku zamiast normalnego wywołania metody: [self.locationManager performSelector:@selector(requestAlwaysAuthorization)];. Może jest to oczywiste dla innych ludzi, ale zajęło mi to trochę czasu, aby się zorientować. Myślę, że to właściwe rozwiązanie do czasu wydania ostatecznego Xcode 6.
VinceFior,

2
Właściwym rozwiązaniem jest kompilacja za pomocą Xcode 6. Jeśli budujesz za pomocą Xcode 5, nie musisz żądać autoryzacji, jest to automatyczne.
progrmr

Możesz mieć rację. Obawiałem się, że chcę, aby mój kod skompilował się w Xcode 5 (nawet jeśli nie będzie działał na iOS 8, chyba że skompilowany w Xcode 6), podczas gdy mój zespół przejdzie na Xcode 6. Ale może lepiej jest napisać kod normalnie i nie scalimy go, dopóki nie przejdziemy do Xcode 6 .. Dzięki.
VinceFior,

@VinceFior zalecanym podejściem jest warunkowa kompilacja przy użyciu zdefiniowanego makra SDK __IPHONE_OS_VERSION_MAX_ALLOWED( #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000)
Steven Kramer

50
- (void)startLocationManager
{
    locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;
    locationManager.distanceFilter = kCLDistanceFilterNone; //whenever we move
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;

    [locationManager startUpdatingLocation];
    [locationManager requestWhenInUseAuthorization]; // Add This Line


}

I do Twojego pliku info.plist wprowadź opis zdjęcia tutaj


1
Znaleziono podobne rozwiązanie w bardziej opisowy sposób na datacalculation.blogspot.in/2014/11/…
iOS Test

2
@Hemang: Według dokumentacji Apple Dev: Bezpiecznie jest uruchomić usługi lokalizacyjne przed ustaleniem statusu autoryzacji aplikacji. Chociaż można uruchomić usługi lokalizacyjne, usługi te nie dostarczają żadnych danych, dopóki status autoryzacji nie zmieni się na kCLAuthorizationStatusAuthorizedAlways lub kCLAuthorizationStatusAuthorizedWhenInUse.
Andrew

Trochę za późno, ale polecam ukryć nieistotne części pliku plist, szczególnie FacebookAppID
Przemysław Wrzesiński

Dzięki Ale to tylko próbna próbka :)
neo D1

Ważne jest również, aby projekt wskazywał właściwy katalog info.plist (ten, w którym zdefiniowano klucz). Jest to określone w ustawieniach kompilacji projektu w pliku Info.plist.
wyczyść

30

Według dokumentów Apple:

Począwszy od systemu iOS 8, wymagana jest obecność wartości klucza NSLocationWhenInUseUsageDescriptionlub NSLocationAlwaysUsageDescriptionw pliku Info.plist aplikacji. Konieczne jest również zwrócenie się do użytkownika o zgodę przed rejestracją aktualizacji lokalizacji, dzwoniąc [self.myLocationManager requestWhenInUseAuthorization]lub [self.myLocationManager requestAlwaysAuthorization]zależnie od potrzeb. Ciąg wprowadzony do Info.plist zostanie wyświetlony w kolejnym oknie dialogowym.

Jeśli użytkownik udzieli pozwolenia, będzie to działać jak zwykle. Jeśli odmówią pozwolenia, delegat nie jest informowany o aktualizacjach lokalizacji.


Znalazłem prosty opis tutaj na stronie datacalculation.blogspot.in/2014/11/…
iOS Test

28
- (void)viewDidLoad
{

    [super viewDidLoad];
    self.locationManager = [[CLLocationManager alloc] init];

    self.locationManager.delegate = self;
    if([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]){
        NSUInteger code = [CLLocationManager authorizationStatus];
        if (code == kCLAuthorizationStatusNotDetermined && ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)] || [self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])) {
            // choose one request according to your business.
            if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]){
                [self.locationManager requestAlwaysAuthorization];
            } else if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) {
                [self.locationManager  requestWhenInUseAuthorization];
            } else {
                NSLog(@"Info.plist does not contain NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription");
            }
        }
    }
    [self.locationManager startUpdatingLocation];
}

>  #pragma mark - CLLocationManagerDelegate

    - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
    {
        NSLog(@"didFailWithError: %@", error);
        UIAlertView *errorAlert = [[UIAlertView alloc]
                                   initWithTitle:@"Error" message:@"Failed to Get Your Location" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [errorAlert show];
    }

    - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
    {
        NSLog(@"didUpdateToLocation: %@", newLocation);
        CLLocation *currentLocation = newLocation;

        if (currentLocation != nil) {
            longitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.longitude];
            latitudeLabel.text = [NSString stringWithFormat:@"%.8f", currentLocation.coordinate.latitude];
        }
    }

W iOS 8 musisz zrobić dwie dodatkowe rzeczy, aby uruchomić lokalizację: Dodaj klucz do Info.plist i poproś o autoryzację od menedżera lokalizacji z prośbą o uruchomienie. Istnieją dwa klucze Info.plist do nowej autoryzacji lokalizacji. Wymagany jest jeden lub oba z tych kluczy. Jeśli nie ma żadnego z tych kluczy, możesz wywołać startUpdatingLocation, ale menedżer lokalizacji tak naprawdę się nie uruchomi. Nie wysyła też komunikatu o błędzie do delegata (ponieważ nigdy się nie uruchomił, nie może zawieść). Nie powiedzie się również, jeśli dodasz jeden lub oba klucze, ale zapomnisz wyraźnie zażądać autoryzacji. Pierwszą rzeczą, którą musisz zrobić, to dodać jeden lub oba następujące klucze do pliku Info.plist:

  • NSLocationWhenInUseUsageDescription
  • NSLocationAlwaysUsageDescription

Oba klucze biorą ciąg

który opisuje, dlaczego potrzebujesz usług lokalizacyjnych. Możesz wpisać ciąg „Lokalizacja jest wymagana, aby dowiedzieć się, gdzie jesteś”, który, podobnie jak w iOS 7, można zlokalizować w pliku InfoPlist.strings.

wprowadź opis zdjęcia tutaj


19

Moje rozwiązanie, które można skompilować w Xcode 5:

#ifdef __IPHONE_8_0
    NSUInteger code = [CLLocationManager authorizationStatus];
    if (code == kCLAuthorizationStatusNotDetermined && ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)] || [self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])) {
        // choose one request according to your business.
        if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]){
            [self.locationManager requestAlwaysAuthorization];
        } else if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) {
            [self.locationManager  requestWhenInUseAuthorization];
        } else {
            NSLog(@"Info.plist does not contain NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription");
        }
    }
#endif
    [self.locationManager startUpdatingLocation];

2
Ładne, dynamiczne rozwiązanie do użycia we wszystkich aplikacjach. Chciałbym jednak zmienić kolejność i zamiast sprawdzać iPhone'a 8.0, sprawdziłbym, czy menedżer lokalizacji odpowiada na autoryzację, a następnie uruchomiłem status autoryzacji, aby uzyskać kod. Dzięki temu będzie bardziej uniwersalny.
zirinisp

Pracował również na xCode 7.2.
Totoro

17

Stary kod zapytania o lokalizację nie działa w systemie iOS 8. Możesz wypróbować tę metodę autoryzacji lokalizacji:

- (void)requestAlwaysAuthorization
{
    CLAuthorizationStatus status = [CLLocationManager authorizationStatus];

    // If the status is denied or only granted for when in use, display an alert
    if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status ==        kCLAuthorizationStatusDenied) {
        NSString *title;
        title = (status == kCLAuthorizationStatusDenied) ? @"Location services are off" :   @"Background location is not enabled";
        NSString *message = @"To use background location you must turn on 'Always' in the Location Services Settings";

        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title
                                                            message:message
                                                           delegate:self
                                                  cancelButtonTitle:@"Cancel"
                                                  otherButtonTitles:@"Settings", nil];
        [alertView show];
    }
    // The user has not enabled any location services. Request background authorization.
    else if (status == kCLAuthorizationStatusNotDetermined) {
        [self.locationManager requestAlwaysAuthorization];
    }
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == 1) {
        // Send the user to the Settings for this app
        NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
        [[UIApplication sharedApplication] openURL:settingsURL];
    }
}

UIAlertView został uznany za przestarzały. Zamiast tego należy użyć UIAlertController.
Pasan Premaratne

tak, wiem, że jest przestarzały, ale to również zadziała. ale tak, lepiej użyj UIAlertController dla IOS8.
Nits007ak

12

W iOS 8 musisz zrobić dwie dodatkowe rzeczy, aby uruchomić lokalizację: Dodaj klucz do Info.plist i poproś o autoryzację od menedżera lokalizacji z prośbą o uruchomienie

info.plist:

<key>NSLocationUsageDescription</key>
<string>I need location</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>I need location</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>I need location</string>

Dodaj to do swojego kodu

if (IS_OS_8_OR_LATER)
{
    [locationmanager requestWhenInUseAuthorization];

    [locationmanager requestAlwaysAuthorization];
}

1
nie jest jasne, czy Twój pseudokod jest połączeniem preprocesorowym czy zwykłym
El Dude,

1
Dodaj to do pliku constants.h lub .pch: # zdefiniować IS_OS_8_OR_LATER ([[UIDevice currentDevice] .systemVersion floatValue]> = 8.0)
OxenBoxen

Dlaczego chcesz poprosić o jedno i drugie, powinieneś dodać komentarz wspominający tylko o tym, aby używać jednego lub drugiego w zależności od potrzeb twojej aplikacji
powerj1984,

część info.plist jest łatwa do zrobienia w Unity3d, ale jak dodać część kodową, jeśli używasz unity3d? gdzie ?
CthulhuJon

11

Jeden typowy błąd dla programistów Swift:

Najpierw upewnij się, że dodałeś wartość do plist dla jednego NSLocationWhenInUseUsageDescriptionlub dwóch NSLocationAlwaysUsageDescription.

Jeśli nadal nie widzisz wyskakującego okna z prośbą o autoryzację, sprawdź, czy wstawiasz wiersz var locationManager = CLLocationManager()w viewDidLoadmetodzie kontrolera widoku . Jeśli to zrobisz, nawet jeśli zadzwonisz locationManager.requestWhenInUseAuthorization(), nic się nie pojawi. Wynika to z faktu, że po wykonaniu viewDidLoad zmienna locationManager jest zwalniana (usuwana).

Rozwiązaniem jest zlokalizowanie linii var locationManager = CLLocationManager()na górze metody klasy.


9

Wcześniej [locationManager startUpdatingLocation];dodaj żądanie usług lokalizacyjnych iOS8:

if([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
    [locationManager requestAlwaysAuthorization];

Edytuj aplikację Info.plisti dodaj klucz NSLocationAlwaysUsageDescriptionz wartością ciągu, która będzie wyświetlana użytkownikowi (na przykładWe do our best to preserve your battery life. )

Jeśli Twoja aplikacja potrzebuje usług lokalizacyjnych tylko wtedy, gdy aplikacja jest otwarta, zamień:

requestAlwaysAuthorizationz requestWhenInUseAuthorizationi

NSLocationAlwaysUsageDescriptionz NSLocationWhenInUseUsageDescription.


9

Pracowałem nad aplikacją, która została uaktualniona do iOS 8, a usługi lokalizacyjne przestały działać. Prawdopodobnie pojawi się błąd w obszarze debugowania w następujący sposób:

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

Zrobiłem najmniej inwazyjną procedurę. Najpierw dodaj NSLocationAlwaysUsageDescriptionwpis do swojej info.plist:

Wpisz opis zdjęcia tutaj

Zauważ, że nie podałem wartości tego klucza. To nadal działa i nie martwię się, ponieważ jest to aplikacja wewnętrzna. Jest też tytuł z prośbą o korzystanie z usług lokalizacyjnych, więc nie chciałem robić nic zbędnego.

Następnie utworzyłem warunek dla iOS 8:

if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
    [_locationManager requestAlwaysAuthorization];
}

Następnie locationManager:didChangeAuthorizationStatus:metoda wywołuje:

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:  (CLAuthorizationStatus)status
{
    [self gotoCurrenLocation];
}

A teraz wszystko działa dobrze. Jak zawsze sprawdź dokumentację .


7

Rozwiązanie z kompatybilnością wsteczną:

SEL requestSelector = NSSelectorFromString(@"requestWhenInUseAuthorization");
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined &&
    [self.locationManager respondsToSelector:requestSelector]) {
    [self.locationManager performSelector:requestSelector withObject:NULL];
} else {
    [self.locationManager startUpdatingLocation];
}

Skonfiguruj klucz NSLocationWhenInUseUsageDescription w Info.plist


2
To nie jest poprawne, a co ze sprawą kCLAuthorizationStatusDenied? przeskakuje w inne miejsce i zaczyna aktualizować lokalizację, która jest niepoprawna!
electronix384128

@BenMarten Nie sądzę, że to powinno mieć znaczenie. Powinieneś sobie z tym poradzić locationManager: (CLLocationManager *)manager didFailWithError: (NSError *)error. Zapomniał jednak dodać startUpdatingLocation do instrukcji if, więc po ich zaakceptowaniu lub odrzuceniu tak naprawdę nie wywołuje startUpdateLocation.
Chris

6

Rozwiązanie z wsteczną kompatybilnością, które nie generuje ostrzeżeń Xcode:

SEL requestSelector = NSSelectorFromString(@"requestWhenInUseAuthorization");
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined &&
  [self.locationManager respondsToSelector:requestSelector]) {
((void (*)(id, SEL))[self.locationManager methodForSelector:requestSelector])(self.locationManager, requestSelector);
  [self.locationManager startUpdatingLocation];
} else {
  [self.locationManager startUpdatingLocation];
}

Ustaw NSLocationWhenInUseUsageDescriptionklucz w swoim Info.plist.

W wersji iOS 11.0+ : NSLocationAlwaysAndWhenInUseUsageDescriptionklucz instalacyjny w swoim Info.plist. wraz z innymi 2 kluczami.


To nie jest poprawne, a co ze sprawą kCLAuthorizationStatusDenied? przeskakuje w inne miejsce i zaczyna aktualizować lokalizację, która jest niepoprawna!
electronix384128

To jest dość dziwne, to działa dobrze dla mnie nie w porządku idealnie zarówno z pozwoleniem, jak i niedozwoleniem. Nawet rozwiązanie Jacoba wygląda dokładnie, ale nie działało dla mnie. Dziwne, ale działało !!!
josh

Wywołanie [self.locationManager startUpdatingLocation] bezpośrednio po żądaniu Kiedy InInseseautoryzacja nie ma sensu
Kostia Kim

5

To jest problem z iOS 8 Dodaj to do swojego kodu

if (IS_OS_8_OR_LATER)
{
    [locationmanager requestWhenInUseAuthorization];

    [locationmanager requestAlwaysAuthorization];
}

i do info.plist:

 <key>NSLocationUsageDescription</key>
 <string>I need location</string>
 <key>NSLocationAlwaysUsageDescription</key>
 <string>I need location</string>
 <key>NSLocationWhenInUseUsageDescription</key>
 <string>I need location</string>

NSLocationUsageDescriptionnie jest używany w iOS8 +
Carlos Ricardo

4

Aby uzyskać dostęp do lokalizacji użytkownika w iOS 8, musisz dodać,

NSLocationAlwaysUsageDescription in the Info.plist 

Spowoduje to zapytanie użytkownika o pozwolenie na uzyskanie jego aktualnej lokalizacji.


4

Procedura celu C Postępuj zgodnie z poniższymi instrukcjami:

W systemie iOS-11 W systemie iOS 11 zapoznaj się z odpowiedzią: Dostęp do lokalizacji w systemie iOS 11

Musisz dodać dwa klucze do listy i podać komunikat jak na poniższym obrazku:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription
 3. NSLocationAlwaysUsageDescription

wprowadź opis zdjęcia tutaj Dla iOS-10 i niższych:

NSLocationWhenInUseUsageDescription

wprowadź opis zdjęcia tutaj

locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
if([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]){
    [locationManager requestWhenInUseAuthorization];
}else{
    [locationManager startUpdatingLocation];
} 

Deleguj metody

#pragma mark - Lolcation Update 
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
    NSLog(@"didFailWithError: %@", error);
    UIAlertView *errorAlert = [[UIAlertView alloc]
                               initWithTitle:@"Error" message:@"Failed to Get Your Location" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [errorAlert show];
}
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
    switch (status) {
        case kCLAuthorizationStatusNotDetermined:
        case kCLAuthorizationStatusRestricted:
        case kCLAuthorizationStatusDenied:
        {
            // do some error handling
        }
            break;
        default:{
            [locationManager startUpdatingLocation];
        }
            break;
    }
}
- (void)locationManager:(CLLocationManager *)manager
     didUpdateLocations:(NSArray *)locations
{
    CLLocation *location = [locations lastObject];
    userLatitude =  [NSString stringWithFormat:@"%f", location.coordinate.latitude] ;
    userLongitude =  [NSString stringWithFormat:@"%f",location.coordinate.longitude];
    [locationManager stopUpdatingLocation];
}

Szybka procedura

Postępuj zgodnie z poniższymi instrukcjami:

W systemie iOS-11 W systemie iOS 11 zapoznaj się z odpowiedzią: Dostęp do lokalizacji w systemie iOS 11

Musisz dodać dwa klucze do listy i podać komunikat jak na poniższym obrazku:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription
 3. NSLocationAlwaysUsageDescription

wprowadź opis zdjęcia tutaj Dla iOS-10 i niższych:

wprowadź opis zdjęcia tutaj

import CoreLocation
class ViewController: UIViewController ,CLLocationManagerDelegate {
var locationManager = CLLocationManager()

//MARK- Update Location 
func updateMyLocation(){
    locationManager.delegate = self;
    locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
    if locationManager.respondsToSelector(#selector(CLLocationManager.requestWhenInUseAuthorization)){
       locationManager.requestWhenInUseAuthorization()
    }
    else{
        locationManager.startUpdatingLocation()
    }
}

Deleguj metody

//MARK: Location Update
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
    NSLog("Error to update location :%@",error)
}
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
    switch status {
    case .NotDetermined: break
    case .Restricted: break
    case .Denied:
            NSLog("do some error handling")
        break
    default:
        locationManager.startUpdatingLocation()
    }
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
     let location = locations.last! as CLLocation
    var latitude = location.coordinate.latitude
    var longitude = location.coordinate.longitude

}

Upewnij się, że dodano również NSLocationAlwaysUsageDescription, w przeciwnym razie podczas przesyłania do App Store wystąpi błąd.
Alok

Twoja wiadomość powinna również zawierać informacje, w przeciwnym razie Apple odrzuci aplikację podczas aktualizacji.
Alok

3

Dla tych, którzy używają Xamarin , musiałem dodać kluczNSLocationWhenInUseUsageDescription ręcznie do info.plist, ponieważ nie był on dostępny w menu rozwijanych w Xamarin 5.5.3 Build 6 lub XCode 6.1 - NSLocationUsageDescriptionbył tylko na liście, a to spowodowało, że CLLocationManagernadal zawodzić cicho.


2
        // ** Don't forget to add NSLocationWhenInUseUsageDescription in MyApp-Info.plist and give it a string

        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];
        }
        [self.locationManager startUpdatingLocation];


    // Location Manager Delegate Methods    
    - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
    {
        NSLog(@"%@", [locations lastObject]);

}

2

Mały pomocnik dla wszystkich, którzy mają więcej niż jeden plik Info.plist ...

find . -name Info.plist | xargs -I {} /usr/libexec/PlistBuddy -c 'Add NSLocationWhenInUseUsageDescription string' {} 

Dodanie potrzebnego znacznika do wszystkich plików Info.plist w bieżącym katalogu (i podfolderach).

Innym jest:

find . -name Info.plist | xargs -I {} /usr/libexec/PlistBuddy -c 'Set NSLocationWhenInUseUsageDescription $YOURDESCRIPTION' {} 

Dodanie twojego opisu do wszystkich plików.



2

W iOS9 pojawia się podobny błąd (praca z Xcode 7 i Swift 2): Próbuję uruchomić aktualizacje lokalizacji MapKit bez monitowania o autoryzację lokalizacji. Należy wywołać - [CLLocationManager requestWhenInUseAuthorization] lub - [CLLocationManager requestAlwaysAuthorization]. Śledziłem samouczek, ale nauczyciel korzystał z iOS8 i Swift 1.2. Istnieją pewne zmiany w Xcode 7 i Swift 2, znalazłem ten kod i działa dla mnie dobrze (jeśli ktoś potrzebuje pomocy):

import UIKit
import MapKit
import CoreLocation

class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {

    // MARK: Properties
    @IBOutlet weak var mapView: MKMapView!

    let locationManager = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.locationManager.delegate = self
        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
        self.locationManager.requestWhenInUseAuthorization()
        self.locationManager.startUpdatingLocation()
        self.mapView.showsUserLocation = true

    }

    // MARK: - Location Delegate Methods

    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let location = locations.last
        let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
        let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 1, longitudeDelta: 1))
        self.mapView.setRegion(region, animated: true)
    }

    func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
        print("Errors: " + error.localizedDescription)
    }
}

Na koniec umieściłem to w info.plist: Lista właściwości informacji: NSLocationWhenInUseUsageDescription Wartość: Aplikacja potrzebuje serwerów lokalizacji dla personelu


2

Aby uzyskać dostęp do lokalizacji użytkowników w iOS. Musisz dodać dwa klucze

NSLocationWhenInUseUsageDescription

NSLocationAlwaysUsageDescription

do pliku Info.plist.

    <key>NSLocationWhenInUseUsageDescription</key>
    <string>Because I want to know where you are!</string>
    <key>NSLocationAlwaysUsageDescription</key>
    <string>Want to know where you are!</string>

Zobacz to poniżej obrazu.

Obraz Info.plist


1
  1. Dodaj klucz NSLocationWhenInUseUsageDescriptionlub NSLocationAlwaysUsageDescription(użycie GPS w tle) ze sznurkiem z prośbą o użycie GPS na każdym info.plistz każdego celu.

  2. Poproś o pozwolenie, uruchamiając:

    [self initLocationManager: locationManager];

Gdzie initLocationManagerjest:

// asks for GPS authorization on iOS 8
-(void) initLocationManager:(CLLocationManager *) locationManager{

    locationManager = [[CLLocationManager alloc]init];

    if([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)])
        [locationManager requestAlwaysAuthorization];
}

Pamiętaj, że jeśli nie ma kluczy info.plistdla każdego celu, aplikacja nie zapyta użytkownika. ifZapewnia kompatybilność z iOS 7 i respondsToSelector:metoda gwarantuje kompatybilność w przyszłości, a nie tylko rozwiązania problemu dla iOS 7 i 8.


0

Problemem było dla mnie to, że klasa, która była tą klasą, CLLocationManagerDelegatebyła prywatna, co uniemożliwiło wywołanie wszystkich metod delegowania. Chyba nie jest to bardzo częsta sytuacja, ale pomyślałem, że wspomnę o tym na wypadek, gdyby ktokolwiek pomógł.


0

Dodam te klucz InfoPlist.stringsw iOS 8.4, mini iPad 2. To działa też. Nie ustawiam żadnego klucza, na przykład NSLocationWhenInUseUsageDescriptionw moim Info.plist.


InfoPlist.strings :

"NSLocationWhenInUseUsageDescription" = "I need GPS information....";

as in iOS 7Oparty na tym wątku , jak powiedział , można zlokalizować w pliku InfoPlist.strings. W moim teście klucze te można skonfigurować bezpośrednio w pliku InfoPlist.strings.

Pierwszą rzeczą, którą musisz zrobić, to dodać jeden lub oba następujące> klucze do pliku Info.plist:

  • NSLocationWhenInUseUsageDescription
  • NSLocationAlwaysUsageDescription

Oba klucze pobierają ciąg znaków, który opisuje, dlaczego potrzebujesz usług lokalizacyjnych. Możesz wpisać ciąg „Lokalizacja jest wymagana, aby dowiedzieć się, gdzie jesteś”, który, podobnie jak w iOS 7 , można zlokalizować w pliku InfoPlist.strings.


AKTUALIZACJA:

Myślę, że @IOSmetoda jest lepsza. Dodaj klucz do Info.plistpustej wartości i dodaj zlokalizowane ciągi do InfoPlist.strings.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.