• Programmazione Android
  • CORSI ONLINE
  • Web Agency

Logo

Corsi di programmazione web e mobile online
Navigation
  • Home
  • CORSI ONLINE
  • Tutorial Pratici
  • GUIDE COMPLETE
    • Corso completo di C
    • Corso videogame con Cocos2d
    • Programmazione Cocoa Touch
  • Sezioni
    • Libri e manuali
    • Tips & Tricks
    • Risorse utili
    • Strumenti di Sviluppo
    • Materiale OpenSource
    • Framework
    • Guide Teoriche
    • Guide varie
    • Grafica e Design
    • iPad
    • News
    • Video Tutorial
    • Windows Phone
  • Pubblicità
  • About
    • Chi siamo
    • Pubblicazioni
    • Collabora
    • Sostieni devAPP

CLLocationManager e iOS8

By IgnazioC | on 28 Novembre 2014 | 0 Comment
Risorse utili

TL;DR Alla fine dell’articolo trovate un progetto completo con una classe per risolvere i più comuni problemi con CLLocationManager e iOS8 🙂

Generalmente le nuove versioni del sistema di iOS sono retro-compatibili, potete prendere del codice scritto per iOS(x) compilarlo con iOS(y) con x < y e tutto generalmente funziona senza problemi.

In qualche caso purtroppo non è così, e il nuovo CLLocationManager ne è un esempio. Molti infatti riscontrano un problema con le loro app passando ad Xcode 6 (e quindi all’sdk di ios8), nell’utilizzo del CLLocationManager che sembra apparentemente  non funzionare.

Andando a dare un’occhiata all’API-diff tra iOS 7.1 e iOS 8.0 (qui) si notano due nuovi metodi:

- [CLLocationManager requestAlwaysAuthorization]
- [CLLocationManager requestWhenInUseAuthorization]

e due nuovi valori per l’enum CLAuthorizationStatus:

Added kCLAuthorizationStatusAuthorizedAlways
Added kCLAuthorizationStatusAuthorizedWhenInUse
Deprecated kCLAuthorizationStatusAuthorized

iOS 8 infatti prevede due nuovi tipi di autorizzazione: possiamo autorizzare un’app per ricevere informazioni sulla nostra posizione soltanto quando l’app è attiva (foreground) oppure sempre (anche in backgroud) e il vecchio modo di usare il CLLocationManager richiamando semplicemente il metodo startUpdatingLocation non è più sufficiente.

La prima cosa da fare quindi è decidere se la vostra app richiede il primo o il secondo tipo di autorizzazione, se state progettando un’app per tracciare il percorso fatto in auto probabilmente vorrete avere l’accesso alla posizione anche in background, viceversa è sufficiente ottenere questa informazione in foreground.

Fatta questa scelta il primo step è quello di aggiungere nel file .plist dell’applicazione una stringa di testo per spiegare all’utente *perché* volete avere accesso alla sua posizione. Questa stringa verrà mostrata dal sistema operativo al momento della richiesta di accesso e nei settings dell’applicazione

Le chiavi da aggiungere al file plist sono due, a seconda del tipo di permesso che vi serve

NSLocationWhenInUseUsageDescription
//Oppure
NSLocationAlwaysUsageDescription

Questo è un esempio di plist:

CLLocationManager_ios8_1

E questo è il risultato visibile nei settings.

CLLocationManager_explanation

ATTENZIONE: Se dimenticate di aggiungere la relativa chiave, anche se tutto il codice è corretto, la richiesta di accesso non verrà mai mostrata all’utente e la vostra app non riceverà mai la sua posizione.

Specificata quindi la ragione per cui vogliamo ottenere la posizione dell’utente, possiamo passare a modificare il codice per ottenerla. Per richiedere la posizione siamo abituati a scrivere più o meno questo tipo di codice

    locationManager  = [[CLLocationManager alloc] init];
    locationManager.distanceFilter = kCLDistanceFilterNone;
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    locationManager.delegate = self;
    [locationManager startUpdatingLocation];

Ma su iOS8 questo codice non farà scattare la richiesta di permesso verso l’utente, quindi la nostra app non riceverà nessuna notifica.

Bisogna infatti attivamente richiedere il permesso all’utente tramite uno dei  due metodi:

-requestAlwaysAuthorization
-requestWhenInUseAuthorization

E finalmente l’utente potrà accettare o rifiutare la richiesta (notare la stringa di descrizione all’interno dell’alert view)

CLLocationManager_request

Questi metodi sono stati definiti nell’skd di iOS 8, quindi se la vostra app è compabile anche con iOS 7 dovrete prima di tutto verificare la versione del sistema operativo, viceversa l’invocazione di questo metodo causerà un bel crash a runtime.

È possibile (e consigliato) richiedere sempre il permesso, in ogni caso se l’utente ha già approvato o rifiutato non vedrà apparire il messaggio.

Un secondo aspetto da tenere in considerazione è il cambio di stato dei permessi, l’utente potrebbe aver rifiutato il permesso ma poi grazie ad un nostro ulteriore  messaggio (“caro utente se non attivi la localizzazione come faccio a consigliarti i bar qui vicino??”)  potrebbe aver deciso di concederci la grazia, quindi la nostra app deve essere reattiva e aggiornarsi di conseguenza.

Questo può essere ottenuto implementando il metodo locationManager:didChangeAuthorizationStatus e richiamando il metodo startUpdatingLocation all’occorrenza.

Una classe da poter riutilizzare

Questa parte di codice è spesso molto simile in tutte le applicazioni, quindi si presta bene ad essere copia&incollata oppure, ancora meglio, ad essere inglobata in una classe che possa essere riutilizzata in più progetti.

Ho infatti scritto un piccolo esempio di wrapper attorno alla classe CLLocationManager per gestire i casi più comuni, trovate il progetto su github a questo indirizzo: https://github.com/ignazioc/DevAppLocationManager

L’idea di base è quella di poter usare questo wrapper al posto del normale CLLocationManager per evitare di dover scrivere codice diverso per iOS 7 / iOS 8 e soprattutto per evitare di dimenticare tutti quei casi un po’ particolari (cambio di stato, etc) che si possono verificare con la gestione dei permessi.

Ho inoltre preferito semplificare un po’ la gestione, usando i block al posto del delegate e gestendo due soli tipi di errori (al posto dei 17 di CoreLocation), gli unici due errori ai quali sono realmente interessato sono “L’utente ha rifiutato il permesso”  e “L’utente non può darti il permesso”.

La classe si chiama CLLocationManagerWrapper, non è un singleton ed ha semplicemente due metodi:

- (id)initWithAuthType:(CLLocationManageraAuthType)authType
        filterDistance:(CLLocationDistance)distanceFilter
             accuracy:(CLLocationAccuracy)accuracy
       completionBlock:(void(^)(CLLocation *newLocation, CLLocationManagerError error))compltionBlock;

- (void)stopUpdate;

Il primo va utilizzato per inizializzare la classe e passare il block che verrà eseguito per ogni nuova posizione rilevata, il secondo per interrompere la localizzazione.

Questo è un esempio di utilizzo:

   locationManagerW = [[CLLocationManagerWrapper alloc] initWithAuthType:CLLocationManageraAuthTypeWhenInUse
                                                           filterDistance:kCLDistanceFilterNone
                                                                 accuracy:kCLLocationAccuracyHundredMeters
                                                          completionBlock:^(CLLocation *newLocation, CLLocationManagerError error) {
                                                              if (newLocation != nil) {
                                                                  NSLog(@"Ricevuta posizione!");
                                                              } else {
                                                                  NSLog(@"Found error: %@", NSStringFromCLLocationManagerError(error));
                                                              }
                                                              
                                                          }];

Una piccola chiccha… per evitare di dimenticare di aggiungere la stringa al plist, in attesa che apple sollevi un warnin o un errore, nell’inizializzazione della classe trovate questa riga, così l’app non compila fintanto che tutto non sarà corretto 😉

NSAssert([[[NSBundle mainBundle] infoDictionary] valueForKey:@"NSLocationWhenInUseUsageDescription"] != nil, @"Aggiungi la descrizione nel file plist");

Alla prossima and “happy coding”!

 

Share this story:
  • tweet

Tags: CLAuthorizationStatusCLLocationManagerCoreLocation FrameworkGuide varieios 8startUpdatingLocation

Recent Posts

  • Parte il percorso programmatori iOS in Swift su devACADEMY.it

    20 Dicembre 2017 - 0 Comment
  • Android, crittografare dati velocemente con Encryption

    24 Settembre 2018 - 0 Comment
  • Sql2o, accesso immediato ai database tramite Java

    3 Settembre 2018 - 0 Comment
  • Okio, libreria per ottimizzare l’input/output in Java

    27 Agosto 2018 - 0 Comment

Related Posts

  • Novità di iOS 8: Le estensioni

    5 Dicembre 2014 - 0 Comment
  • Usare assets “resolution-independent” con Xcode 6

    26 Settembre 2014 - 0 Comment

Author Description

No Responses to “CLLocationManager e iOS8”

Leave a Reply

Your email address will not be published. Required fields are marked *


*
*

Corso online di programmazione android e java

SEZIONI

  • Android
  • Comunicazioni
  • Contest
  • Corsi ed Eventi
  • Corso completo di C
  • Corso programmazione videogiochi
  • Framework
  • Grafica e Design
  • Guida rapida alla programmazione Cocoa Touch
  • Guide Teoriche
  • Guide varie
  • iPad
  • Le nostre applicazioni
  • Libri e manuali
  • Materiale OpenSource
  • News
  • Pillole di C++
  • Progetti completi
  • Risorse utili
  • Strumenti di Sviluppo
  • Swift
  • Tips & Tricks
  • Tutorial Pratici
  • Video Tutorial
  • Windows Phone

Siti Amici

  • Adrirobot
  • Allmobileworld
  • Apple Notizie
  • Apple Tribù
  • Avvocato360
  • Blog informatico 360°
  • bubi devs
  • fotogriPhone
  • GiovaTech
  • iApp-Mac
  • iOS Developer Program
  • iPodMania
  • MelaRumors
  • Meritocracy
  • SoloTablet
  • TecnoUser
  • Privacy & Cookie Policy
©2009-2018 devAPP - All Rights Reserved | Contattaci
devAPP.it è un progetto di DEVAPP S.R.L. - Web & Mobile Agency di Torino
Str. Volpiano, 54 - 10040 Leini (TO) - C.F. e P.IVA 11263180017 - REA TO1199665 - Cap. Soc. € 10.000,00 i.v.

devACADEMY.it

Vuoi imparare a programmare?

Iscriviti e accedi a TUTTI i corsi con un’unica iscrizione.
Oltre 70 corsi e migliaia di videolezioni online e in italiano a tua disposizione.

ISCRIVITI SUBITO