Pour donner la position d'un point sur la Terre, on utilise souvent sa latitude et sa longitude.
- Un parallèle est un cercle imaginaire parallèle à l'équateur.
- La latitude est la distance mesurée en degrés qui sépare un parallèle de l'équateur.
- Un méridien est un demi-cercle imaginaire qui relie les deux pôles.
- Les méridiens de référence utilisés sont celui de Greenwich (longitude 0°) et celui de l'observatoire de Paris (2°20'14,025 à l'est du méridien de Greenwich).
- La longitude est la distance mesurée en degrés qui sépare un méridien du méridien de référence.
Si vous avez un peu de mal à vous représenter tout ça, je vous conseille de regarder la figure suivante.
Ces quelques notions de base étant posées, nous allons définir une application qui renvoie la longitude et la latitude d'un device (iPhone, iPod Touch ou iPad 2). Les informations de géolocalisation utilisées pourront provenir de réseaux cellulaires, Wi-Fi et/ou GPS.
Attaquons sans plus tarder.
Commencez par définir un nouveau projet basé sur le modèle
Single View Application et donnez-lui le nom « ouSuisJe ». Toutes les méthodes relatives à la géolocalisation se trouvant dans le framework
CoreLocation, la première étape va consister à ajouter ce framework à l'application.
Comme à la figure suivante, cliquez sur la première icône affichée dans le volet de navigation (1) et sélectionnez l'onglet
Build Phases dans la zone d'édition (2). Développez l'entrée
Link Binary With Libraries (3). Cliquez sur l'icône
+ (4), sélectionnez le framework
CoreLocation.framework et cliquez sur
Add (5).
Nous allons afficher les coordonnées du device dans un
Label. Pour ce faire, cliquez sur
MainStoryboard.storyboard dans le volet de navigation (1) et ajoutez un
Label à la vue de l'application (2), comme à la figure suivante. Agrandissez ce contrôle et sélectionnez
Show the Attributes inspector dans le volet des utilitaires (3). Affectez la valeur « Recherche de la position en cours » à la propriété
Text (4) et la valeur « 10 » à la propriété
Lines (5).
Pourquoi affecter la valeur 10 à la propriété Lines du Label ?
Ce
Label va être utilisé pour afficher des informations relatives à la position du device. La méthode utilisée pour obtenir ces informations est très « verbeuse ». C'est la raison pour laquelle autant de lignes sont attribuées au
Label. Si vous limitez la taille du
Label à deux ou trois lignes seulement, l'information affichée a toutes les chances d'être tronquée !
Cliquez sur l'icône
Show the Assistant editor dans la barre d'outils. Contrôle-glissez-déposez le
Label juste au-dessus du
@end final et définissez l'outlet
maPosition pour le
Label.
Cliquez sur
ViewController.h dans le volet de navigation et ajoutez une instruction
#import au fichier d'en-têtes pour faire référence au framework
CoreLocation :
Code : Objective-C | #import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
...
|
Comme l'indique la documentation Apple, les informations de géolocalisation sont obtenues à travers la classe
CLLocationManager. Cette dernière est accessible à travers le protocole
CLLocationManagerDelegate. Vous allez donc devoir implémenter ce protocole dans le code de l'application.
Cliquez sur
ViewController.h dans le volet de navigation et ajoutez le protocole dans la déclaration de l'interface :
Code : Objective-C | @interface ViewController : UIViewController <CLLocationManagerDelegate>
|
Définissez ensuite la variable d'instance
locationManager de classe
CLLocationLManager :
Code : Objective-C | @interface ViewController : UIViewController <CLLocationManagerDelegate>
{
CLLocationManager* locationManager;
}
|
Comme nous le verrons un peu plus loin, c'est par l'intermédiaire de cette variable d'instance que le processus de géolocalisation sera lancé.
Le fichier d'en-têtes doit maintenant avoir l'allure suivante :
Code : Objective-C | #import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
@interface ViewController : UIViewController <CLLocationManagerDelegate>
{
CLLocationManager* locationManager;
}
@property (weak, nonatomic) IBOutlet UILabel *maPosition;
@end
|
Il est temps de passer à la définition du code. Cliquez sur
ViewController.m dans le volet de navigation et complétez la méthode
viewDidLoad comme suit :
Code : Objective-C 1
2
3
4
5
6
7
8
9
10
11
12 | - (void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
if ([CLLocationManager locationServicesEnabled])
{
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = 100.0f;
[locationManager startUpdatingLocation];
}
}
|
N'ayez crainte, nous allons passer en revue toutes ces instructions.
Ligne 4, l'objet
locationManager est défini et initialisé :
Code : Objective-C | locationManager = [[CLLocationManager alloc] init];
|
L'instruction de la ligne 5 teste si le service de géolocalisation est disponible et activé :
Code : Objective-C | if ([CLLocationManager locationServicesEnabled]) {
|
Cette instruction est nécessaire : en effet, si le mode « Avion » est activé ou si les périphériques de géolocalisation ne sont pas en mesure de fournir des informations, il est inutile de chercher à en obtenir.
L'instruction de la ligne 7 affecte la valeur
self à la propriété
delegate de l'objet
locationManager afin d'indiquer que les événements relatifs à la géolocalisation doivent être traités dans
ViewController.m :
Code : Objective-C | locationManager.delegate = self;
|
L'instruction de la ligne 8 définit la précision désirée :
Code : Objective-C | locationManager.desiredAccuracy = kCLLocationAccuracyBest;
|
La constante utilisée (
kCLLocationAccuracyBest) demande la meilleure précision possible. Si vous le souhaitez, vous pouvez utiliser une autre précision. Par exemple,
kCLLocationAccuracyHundredMeters pour obtenir une précision de cent mètres.
Consultez la section intitulée « Core Location Constants Reference » dans la documentation Apple pour prendre connaissance de toutes les constantes disponibles.
Mais pourquoi ne pas utiliser systématiquement la meilleure précision possible ?
Cela semble en effet une bonne solution… si la batterie du device est entièrement chargée. Dans le cas contraire, la géolocalisation fonctionnera certes d'une façon très précise, mais pour une durée assez courte. En effet, précision et consommation en énergie vont de pair. À vous de trouver le juste milieu en fonction de ce que doit faire votre application…
La ligne 9 définit la distance de déplacement minimale du device avant qu'une mise à jour de la position ne soit effectuée. Dans cet exemple, il faudra que le device se déplace de 100 mètres pour qu'une notification de changement de position soit faite :
Code : Objective-C | locationManager.distanceFilter = 100.0f;
|
La ligne 10 exécute la méthode
startUpdatingLocation. En d'autres termes, elle demande au device de mettre à jour de façon régulière ses coordonnées géographiques, en accord avec les paramètres définis précédemment (précision et déplacement minimum pour mise à jour) :
Code : Objective-C | [locationManager startUpdatingLocation];
|
L'implémentation du protocole
CLLocationManagerDelegate et la définition de l'objet
locationManager ne sont pas suffisantes. Vous devez également faire appel aux méthodes :
- locationManager:didUpdateToLocation:fromLocation: pour savoir si une nouvelle position est disponible ;
- locationManager:didFailWithError: qui indique, le cas échéant, qu'aucune position ne peut être déterminée pour le device.
Ces deux méthodes sont abondamment documentées dans la documentation Apple qui donne, entre autres choses, les en-têtes de ces deux fonctions. Ajoutez ces en-têtes dans le fichier
ViewController.m et complétez-les comme suit :
Code : Objective-C 1
2
3
4
5
6
7
8
9
10
11
12 | - (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
maPosition.text = [newLocation description];
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
maPosition.text = [error description];
}
|
Chaque fois qu'une mise à jour de la position du device est générée, la méthode
locationManager:didUpdateToLocation:fromLocation: est exécutée. Le nouvel emplacement (
[newLocation description]) est alors affiché dans le
Label :
Code : Objective-C | maPosition.text = [newLocation description];
|
Lorsque le système de géolocalisation du device n'est pas en mesure de donner des coordonnées géographiques, la méthode
locationManager:didFailWithError: est exécutée. Le message d'erreur (
[error description];) est alors affiché dans le Label (
maPosition.text) :
Code : Objective-C | maPosition.text = [error description];
|
Allez-y, lancez l'application, vous l'avez bien mérité !
Je suppose que vous testez cette application dans le simulateur iOS. Dans ce cas, une boîte de dialogue devrait s'afficher, comme à la figure suivante.
Validez en cliquant sur
OK. Regardez la figure suivante, le résultat est plutôt fantaisiste.
Pour avoir des résultats cohérents, une seule solution : testez l'application sur un device !
Le code de l'application se trouve dans le dossier
ouSuisJe.
ViewController.h
Secret (cliquez pour afficher)
Code : Objective-C | #import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
@interface ViewController : UIViewController <CLLocationManagerDelegate>
{
CLLocationManager* locationManager;
}
@property (weak, nonatomic) IBOutlet UILabel *maPosition;
@end
|
ViewController.m
Secret (cliquez pour afficher)
Code : Objective-C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 | #import "ViewController.h"
@implementation ViewController
@synthesize maPosition;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
if ([CLLocationManager locationServicesEnabled]) {
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = 1000.0f;
[locationManager startUpdatingLocation];
}
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
maPosition.text = [newLocation description];
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
maPosition.text = [error description];
}
- (void)viewDidUnload
{
[self setMaPosition:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
@end
|