Os Serviços de Localização não funcionam no iOS 8


608

Meu aplicativo que funcionou bem no iOS 7 não funciona com o SDK do iOS 8.

CLLocationManagernão retorna um local e também não vejo meu aplicativo em Configurações -> Serviços de localização . Eu fiz uma pesquisa no Google sobre o assunto, mas nada aconteceu. O que pode estar errado?


Você também pode usar isso como aplicativo de referência para a solução github.com/jbanford/ConstantLocationUpdates
— ashok Vadivelu

19
Eu postei sobre algumas das alterações para a locação no iOS 8 aqui: nevan.net/2014/09/core-location-manager-changes-in-ios-8
— rei Nevan

2
Você pode tentar usar esta biblioteca que simplifica as APIs de localização central e expõe uma boa interface baseada em blocos e normaliza todas as diferenças entre as diferentes versões do iOS (divulgação completa: sou o autor): github.com/lmirosevic/GBLocation
— lms

Encontrei alguma referência aqui datacalculation.blogspot.in/2014/11/…
— Teste do iOS

2
@nevanking Você senhor! preciso de uma coroa! Eu tenho lutado com esse problema desde a mudança e ainda não encontrei um "guia" para consertá-lo, que fosse noob amigável. Seu guia fez um idiota como eu, lida com o problema sozinho. Muito obrigado por esse link.
— Patrick R

Respostas:


1086

Acabei resolvendo meu próprio problema.

Aparentemente, no iOS 8 SDK, requestAlwaysAuthorization(para localização em segundo plano) ou requestWhenInUseAuthorization(localização somente em primeiro plano), ligueCLLocationManager é necessária a antes de iniciar as atualizações de localização.

Também precisa haver NSLocationAlwaysUsageDescriptionou NSLocationWhenInUseUsageDescriptiondigitar Info.plistuma mensagem a ser exibida no prompt. Adicionando estes resolveu o meu problema.

enter image description here

Espero que isso ajude mais alguém.

EDIT: Para obter informações mais abrangentes, consulte: Core-Location-Manager-Changes-in-ios-8


6
você pode compartilhar o valor exato atualizado no Info.plist? Não estou conseguindo ver essa chave no meu Info.plist. Eu adicionei e ainda não parece funcionar. Eu estou usando Swift, iOS8 e XCode 6 beta 4
— Vijay Kumar AB

4
@Vjay - você precisa editar o arquivo Info.plist em um editor, não pode definir essas chaves no Xcode (a partir da versão 6).
— Kendall Helmstetter Gelner

11
Apenas um lembrete: se você não quiser mostrar uma explicação personalizada ao usuário, basta definir essa chave como uma string vazia.
— nonamelive

7
Você precisa manter seu locationManager para fazê-lo funcionar. para fazer o seu CLLocationManager como uma propriedade forte
— Vassily

273
EU AMO que você não receba nenhum erro, nenhum aviso, nenhuma mensagem de log, NADA se você deixar de fora a entrada do plist. Basicamente, a Apple criou uma chamada de API que não faz NADA se você não tiver a entrada plist apropriada. Obrigado a @OrtwinGentz ​​por descobrir isso.
— MobileVet 22/09

314

Eu estava puxando meu cabelo com o mesmo problema. O Xcode fornece o erro:

Tentando iniciar MapKitatualizações de local sem solicitar autorização de local. Deve ligar -[CLLocationManager requestWhenInUseAuthorization]ou -[CLLocationManager requestAlwaysAuthorization]primeiro.

Mas mesmo se você implementar um dos métodos acima, ele não solicitará ao usuário, a menos que haja uma entrada no info.plist para NSLocationAlwaysUsageDescriptionouNSLocationWhenInUseUsageDescription .

Adicione as seguintes linhas ao seu info.plist em que os valores da sequência representam o motivo pelo qual você precisa acessar a localização dos usuários

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

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

Eu acho que essas entradas podem estar ausentes desde que iniciei este projeto no Xcode 5. Acho que o Xcode 6 pode adicionar entradas padrão para essas chaves, mas não foi confirmado.

Você pode encontrar mais informações sobre essas duas configurações aqui


13
xcode 6 não adicionar essas chaves por padrão, se você pretende implementar CLLocationManager você deve adicioná-los manualmente
— Wesley Smith

1
Eu também tive que adicioná-los manualmente, não consegui adicionar através da visualização RawValues ​​do info.plist no Xcode6!
— Kendall Helmstetter Gelner

1
Eu procurei eternamente por isso. Minha mensagem [CLLLocationManager authenticationStatus] estava retornando apenas um valor de <nil>. Após adicionar as teclas acima, ele começou a retornar as respectivas enumerações para a saída das mensagens. Pelo que encontrei, este é um bug conhecido do iOS 8, mas não consegui encontrar nada no meu contexto há séculos. Graças um mil!
— precisa saber é o seguinte

4
Eu gosto do valor da string que você coloca #
— Chris Chen

1
A mensagem aparecerá como a sub-mensagem no Alerta que pergunta se o usuário gostaria de compartilhar sua localização. Como tal, simplesmente estar vazio (em branco) parece fazer mais sentido no meu aplicativo. Uma explicação de por que você deseja usar o local também faria sentido. No entanto, NSLocationWhenInUseUsageDescription não se comportou conforme o esperado para mim (ou seja, continuou obtendo permissão negada, mesmo que o valor de retorno estivesse correto). NSLocationAlwaysUsageDescription funcionou bem.
— bob Arcady

104

Para garantir que isso seja compatível com o iOS 7, verifique se o usuário está executando o iOS 8 ou iOS 7. Por exemplo:

#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
A melhor maneira de verificar a versão é verificar para ver se o objeto tem que seletor, por exemplo: if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) { ...
— progrmr

1
Tive problemas ao implementar a solução da @ progrmr ao criar no Xcode 5, pois ele não sabe qual é o requestAlwaysAuthorizationmétodo. Minha solução adicional era usar esta linha na ifdeclaração, em vez de uma chamada de método normal: [self.locationManager performSelector:@selector(requestAlwaysAuthorization)];. Talvez isso seja óbvio para outras pessoas, mas levei um tempo para descobrir. Eu acho que é a solução certa até o final do Xcode 6 ser lançado.
— VinceFior 9/09/14

2
A solução certa é construir com o Xcode 6. Se você estiver construindo com o Xcode 5, não precisará solicitar autorização, é automático.
— progrmr

Você pode ter razão. Minha preocupação era que eu queria que meu código fosse compilado no Xcode 5 (mesmo que ele não funcione no iOS 8, a menos que seja compilado no Xcode 6) enquanto minha equipe faz a transição para o Xcode 6. Mas talvez seja um fluxo de trabalho melhor escrever o código normalmente e não mesclá-lo até passarmos para o Xcode 6 .. Obrigado.
— precisa saber é o seguinte

@VinceFior a abordagem recomendada é compilar condicionalmente usando a macro SDK definido __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


}

E para o seu arquivo info.plist insira a descrição da imagem aqui


1
Solução semelhante encontrada de maneira mais descritiva em datacalculation.blogspot.in/2014/11/…
— Teste do iOS

2
@ Hemang: De acordo com a Apple Dev Documentation: É seguro iniciar os serviços de localização antes que o status de autorização do seu aplicativo seja determinado. Embora você possa iniciar os serviços de localização, esses serviços não entregam dados até que o status da autorização seja alterado para kCLAuthorizationStatusAuthorizedAlways ou kCLAuthorizationStatusAuthorizedWhenInUse.
— 28414 Andrew Andrew

Um pouco tarde, mas eu recomendo que você ocultar partes irrelevantes do seu arquivo plist, especialmente FacebookAppID
— Przemysław Wrzesinski

Obrigado, mas isso é apenas uma amostra manequim :)
— neo D1

Também é importante que o projeto esteja apontando para o info.plist correto (aquele em que a chave está definida). Isso é determinado nas configurações de criação do projeto em Arquivo Info.plist.
— clearlight

30

De acordo com os documentos da Apple:

No iOS 8, é necessária a presença de um valor-chave NSLocationWhenInUseUsageDescriptionou NSLocationAlwaysUsageDescriptionno arquivo Info.plist do seu aplicativo. Também é necessário solicitar permissão do usuário antes de se registrar para atualizações de local, ligando [self.myLocationManager requestWhenInUseAuthorization]ou[self.myLocationManager requestAlwaysAuthorization] dependendo da sua necessidade. A seqüência que você inseriu no Info.plist será exibida na caixa de diálogo a seguir.

Se o usuário conceder permissão, os negócios serão normais. Se eles negarem permissão, o delegado não será informado das atualizações de local.


Encontrei uma descrição simples aqui em datacalculation.blogspot.in/2014/11/…
— Teste do iOS

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];
        }
    }

No iOS 8, você precisa fazer duas coisas extras para que o local funcione: adicione uma chave ao seu Info.plist e solicite autorização ao gerente do local solicitando que ele inicie. Existem duas chaves Info.plist para a nova autorização de local. Uma ou ambas as chaves são necessárias. Se nenhuma das chaves estiver lá, você poderá chamar startUpdatingLocation, mas o gerenciador de local não será iniciado. Também não enviará uma mensagem de falha para o delegado (como nunca foi iniciado, não pode falhar). Também falhará se você adicionar uma ou ambas as chaves, mas esquecer de solicitar explicitamente a autorização. Portanto, a primeira coisa que você precisa fazer é adicionar uma ou ambas as seguintes chaves ao seu arquivo Info.plist:

  • NSLocationWhenInUseUsageDescription
  • NSLocationAlwaysUsageDescription

Ambas as teclas recebem uma string

que é uma descrição do motivo pelo qual você precisa de serviços de localização. Você pode inserir uma sequência como "O local é necessário para descobrir onde você está" que, como no iOS 7, pode ser localizado no arquivo InfoPlist.strings.

insira a descrição da imagem aqui


19

Minha solução que pode ser compilada no 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
Solução dinâmica agradável, para usar em todos os aplicativos. Eu mudaria a ordem e, em vez de verificar o iphone 8.0, verificaria se o gerente de local responde à autorização e executaria o status da autorização para obter o código. Isso tornará mais universal.
— Zirinisp

Também funcionou no xCode 7.2.
— Totoro

17

O código antigo para perguntar a localização não funcionará no iOS 8. Você pode tentar este método para obter autorização de localização:

- (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];
    }
}

O UIAlertView foi descontinuado. Você deve usar UIAlertController.
— Pasan Premaratne

Sim, eu sei que está obsoleto, mas isso também vai funcionar. mas sim, é melhor usar UIAlertController para IOS8.
— Nits007ak

12

No iOS 8, você precisa fazer duas coisas extras para que o local funcione: adicione uma chave ao seu Info.plist e solicite autorização ao gerente do local, solicitando que ele inicie

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>

Adicione isto ao seu código

if (IS_OS_8_OR_LATER)
{
    [locationmanager requestWhenInUseAuthorization];

    [locationmanager requestAlwaysAuthorization];
}

1
não está claro se o pseudocódigo é uma chamada pré-processador ou uma chamada normal
— El Cara

1
Adicione isto a sua constants.h ou arquivo .pch: IS_OS_8_OR_LATER #define ([[UIDevice currentDevice] .systemVersion floatValue]> = 8,0)
— OxenBoxen

Por que você iria solicitar tanto, você deve adicionar um comentário mencionar apenas para usar um ou o outro, dependendo de suas necessidades de aplicação
— powerj1984

a parte info.plist é fácil de fazer no Unity3d, mas como eu adicionaria a parte do código se estivesse usando o unity3d? Onde ?
— CthulhuJon

11

Um erro comum para desenvolvedores Swift:

Primeiro, certifique-se de adicionar um valor ao plist para um NSLocationWhenInUseUsageDescriptionou outro NSLocationAlwaysUsageDescription.

Se você ainda não estiver vendo uma janela solicitando autorização, verifique se está colocando a linha var locationManager = CLLocationManager()no viewDidLoadmétodo do seu View Controller . Se você o fizer, mesmo se ligar locationManager.requestWhenInUseAuthorization(), nada será exibido. Isso ocorre depois que o viewDidLoad é executado, a variável locationManager é desalocada (limpa).

A solução é localizar a linha var locationManager = CLLocationManager()na parte superior do método da classe.


9

Antes [locationManager startUpdatingLocation];, adicione uma solicitação de serviços de localização iOS8:

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

Edite o aplicativo Info.pliste adicione a chave NSLocationAlwaysUsageDescriptioncom o valor da string que será exibido ao usuário (por exemplo, We do our best to preserve your battery life.)

Se o seu aplicativo precisar de serviços de localização apenas enquanto o aplicativo estiver aberto, substitua:

requestAlwaysAuthorizationcom requestWhenInUseAuthorizatione

NSLocationAlwaysUsageDescriptioncom NSLocationWhenInUseUsageDescription.


9

Eu estava trabalhando em um aplicativo que foi atualizado para o iOS 8 e os serviços de localização pararam de funcionar. Você provavelmente receberá um erro na área de Depuração da seguinte forma:

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

Eu fiz o procedimento menos invasivo. Primeiro adicione a NSLocationAlwaysUsageDescriptionentrada ao seu info.plist:

Digite a descrição da imagem aqui

Observe que eu não preenchi o valor dessa chave. Isso ainda funciona e não estou preocupado porque esse é um aplicativo interno. Além disso, já existe um título solicitando o uso de serviços de localização, então não queria fazer nada redundante.

Em seguida, criei uma condicional para o iOS 8:

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

Depois disso, o locationManager:didChangeAuthorizationStatus:método é chamado:

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

E agora tudo funciona bem. Como sempre, confira a documentação .


7

Solução com compatibilidade com versões anteriores:

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

Configure a chave NSLocationWhenInUseUsageDescription no seu Info.plist


2
Isso não está correto, e o caso kCLAuthorizationStatusDenied? ele pula para o outro e começa a atualizar o local que não está correto!
— electronix384128

@BenMarten Eu não acho que isso importe. Você deve lidar com isso sozinho locationManager: (CLLocationManager *)manager didFailWithError: (NSError *)error. No entanto, ele esqueceu de adicionar startUpdatingLocation na instrução if, portanto, depois que eles aceitam ou negam, na verdade, ele não chama startUpdateLocation.
— Chris

6

Solução com compatibilidade com versões anteriores que não produz avisos do 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];
}

NSLocationWhenInUseUsageDescriptionChave de instalação no seu Info.plist.

Para iOS versão 11.0+ : NSLocationAlwaysAndWhenInUseUsageDescriptionchave de configuração no seu Info.plist. juntamente com outras 2 teclas.


Isso não está correto, e o caso kCLAuthorizationStatusDenied? ele pula para o outro e começa a atualizar o local que não está correto!
— electronix384128

Isso é muito estranho, isso funciona bem para mim, não funciona perfeitamente bem com permitir e não permitir. Mesmo a solução Jacob parece precisa, mas não funcionou para mim. Estranho, mas funcionou !!!
— josh

Chamando [self.locationManager startUpdatingLocation] logo após requestWhenInUseAuthorization não tem nenhum ponto
— Kostia Kim

5

This is issue with ios 8 Adicione isso ao seu código

if (IS_OS_8_OR_LATER)
{
    [locationmanager requestWhenInUseAuthorization];

    [locationmanager requestAlwaysAuthorization];
}

e para 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>

NSLocationUsageDescriptionnão é usado em iOS8
— Carlos Ricardo

4

Para acessar a localização do usuário no iOS 8, você precisará adicionar,

NSLocationAlwaysUsageDescription in the Info.plist 

Isso solicitará ao usuário a permissão para obter sua localização atual.


4

Procedimento Objective-C Siga as instruções abaixo:

Para iOS-11 Para iOS 11, consulte esta resposta: Acesso à localização do iOS 11

É necessário adicionar duas chaves ao plist e fornecer a mensagem conforme a imagem abaixo:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription
 3. NSLocationAlwaysUsageDescription

insira a descrição da imagem aqui Para iOS-10 e abaixo:

NSLocationWhenInUseUsageDescription

insira a descrição da imagem aqui

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

Métodos de delegação

#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];
}

Procedimento Rápido

Siga as instruções abaixo:

Para iOS-11 Para iOS 11, consulte esta resposta: Acesso à localização do iOS 11

É necessário adicionar duas chaves ao plist e fornecer a mensagem conforme a imagem abaixo:

 1. NSLocationAlwaysAndWhenInUseUsageDescription 
 2. NSLocationWhenInUseUsageDescription
 3. NSLocationAlwaysUsageDescription

insira a descrição da imagem aqui Para iOS-10 e abaixo:

insira a descrição da imagem aqui

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()
    }
}

Métodos de delegação

//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

}

Verifique se NSLocationAlwaysUsageDescription também foi adicionado, caso contrário, você receberá um erro ao fazer o upload na App Store.
— Alok

Sua mensagem também deve ser informativa, caso contrário, a Apple rejeitará o aplicativo durante a revisão do processo.
— Alok

3

Para aqueles que usam o Xamarin , tive que adicionar a chave NSLocationWhenInUseUsageDescriptionao info.plist manualmente, pois ela não estava disponível nas listas suspensas no Xamarin 5.5.3 Build 6 ou no XCode 6.1 - apenas NSLocationUsageDescriptionestava na lista e isso fez CLLocationManagercom que continuasse a falhar silenciosamente.


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

Um pequeno auxiliar para todos vocês que têm mais de um arquivo Info.plist ...

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

Ele adicionará a marca necessária a todos os arquivos Info.plist no diretório atual (e subpastas).

Outro é:

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

Ele adicionará sua descrição a todos os arquivos.



2

Eu recebo um erro semelhante no iOS9 (trabalhando com o Xcode 7 e Swift 2): Tentando iniciar as atualizações de localização do MapKit sem solicitar a autorização da localização. Deve chamar - [CLLocationManager requestWhenInUseAuthorization] ou - [CLLocationManager requestAlwaysAuthorization] primeiro. Eu estava seguindo um tutorial, mas o tutor estava usando o iOS8 e o Swift 1.2. Existem algumas alterações no Xcode 7 e no Swift 2, encontrei esse código e ele funciona bem para mim (se alguém precisar de ajuda):

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)
    }
}

Finalmente, coloquei isso em info.plist: Information Property List: NSLocationWhenInUseUsageDescription Value: aplicativo precisa de servidores de localização para a equipe


2

Para acessar a localização dos usuários no iOS. Você precisa adicionar duas chaves

NSLocationWhenInUseUsageDescription

NSLocationAlwaysUsageDescription

no arquivo 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>

Veja esta imagem abaixo.

Imagem Info.plist


1
  1. Adicione a tecla NSLocationWhenInUseUsageDescriptionou NSLocationAlwaysUsageDescription(uso em segundo plano do GPS) com a corda pedindo para usar o GPS em cada um info.plistde cada alvo.

  2. Peça permissão executando:

    [self initLocationManager: locationManager];

Onde initLocationManagerfica:

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

    locationManager = [[CLLocationManager alloc]init];

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

Lembre-se de que se as chaves não estiverem em cada uma info.plistpara cada destino, o aplicativo não perguntará ao usuário. Ele ifoferece compatibilidade com o iOS 7 e o respondsToSelector:método garante compatibilidade futura, em vez de apenas resolver o problema do iOS 7 e 8.


0

O problema para mim era que a classe CLLocationManagerDelegateera privada, o que impedia que todos os métodos delegados fossem chamados. Acho que não é uma situação muito comum, mas pensei em mencioná-la para o caso de ajudar alguém.


0

Acrescento aqueles chave no InfoPlist.stringsno iOS 8.4, mini-iPad 2. Ele funciona também. Eu não ponho nenhuma chave NSLocationWhenInUseUsageDescriptionno meu Info.plist.


InfoPlist.strings :

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

A base desse segmento , segundo ele as in iOS 7, pode ser localizada no InfoPlist.strings. No meu teste, essas chaves podem ser configuradas diretamente no arquivoInfoPlist.strings .

Portanto, a primeira coisa que você precisa fazer é adicionar uma ou ambas as seguintes chaves ao seu arquivo Info.plist:

  • NSLocationWhenInUseUsageDescription
  • NSLocationAlwaysUsageDescription

Ambas as chaves usam uma sequência que é uma descrição do motivo pelo qual você precisa de serviços de localização. Você pode inserir uma sequência como "O local é necessário para descobrir onde você está" que, como no iOS 7 , pode ser localizado no arquivo InfoPlist.strings.


ATUALIZAR:

Eu acho que @IOSo método é melhor. Adicione chave a Info.plistcom valor vazio e adicione cadeias localizadas a InfoPlist.strings.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.