L'interface et le fichier d'en-têtes étant définis, il ne reste plus qu'à écrire un peu de code pour faire fonctionner tout ce petit monde. Cliquez sur
ViewController.m dans le volet de navigation.
Dans un premier temps, vous allez ajouter un arrière-plan à l'application. Définissez un dossier
Resources dans l'arborescence de l'application, procurez-vous une image de 320x480 pixels et ajoutez-la à ce dossier.
Pour que l'image d'arrière-plan s'affiche dès l'ouverture de l'application, ajoutez l'instruction suivante dans la méthode
viewDidLoad (cette instruction suppose que l'image d'arrière-plan a pour nom « gyro.jpg ») :
Code : Objective-C | self.view.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:@"gyro.jpg"]];
|
Vous allez maintenant définir un objet de classe
UIAccelerometer et l'initialiser. Complétez la méthode
viewDidLoad comme suit :
Code : Objective-C | - (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:@"gyro.jpg"]];
UIAccelerometer *testAccel = [UIAccelerometer sharedAccelerometer];
testAccel.delegate = self;
testAccel.updateInterval = 0.1f;
[mouvement setText:@"Le device est calme"];
}
|
À la ligne 5, nous définissons l'objet
testAccel de type
UIAccelerator. Cet objet est initialisé avec la méthode
sharedAccelerometer, comme indiqué dans la documentation Apple :
Code : Objective-C | UIAccelerometer *testAccel = [UIAccelerometer sharedAccelerometer];
|
La ligne 6 indique que les événements relatifs à l'objet
testAccel seront traités dans la classe courante, c'est-à-dire dans la classe de la vue :
Code : Objective-C | testAccel.delegate = self;
|
À la ligne 7, nous utilisons la propriété
updateInterval pour définir la période de la mise à jour des données fournies par l'accéléromètre. Ici, tous les 1/10 seconde :
Code : Objective-C | testAccel.updateInterval = 0.1f;
|
Enfin, la ligne 8 affiche le message « Le device est calme » dans le
Label mouvement pour indiquer que le device n'est pas agité :
Code : Objective-C | [mouvement setText:@"Le device est calme"];
|
Si je me souviens de ce qui a été dit au début de cette section, il est nécessaire d'implémenter le protocole UIAccelerometerDelegate. Est-ce qu'il ne faudrait pas agir sur le fichier d'en-têtes pour cela ?
Tout à fait exact. D'ailleurs, le message d'avertissement affiché en face de la ligne
testAccel.delegate = self; (figure suivante) le confirme :
Cliquez sur
ViewController.h dans le volet de navigation et ajoutez la référence au delegate dans l'instruction
@interface :
Code : Objective-C | @interface accelerometreViewController : UIViewController <UIAccelerometerDelegate>
{
...
}
|
En consultant la documentation Apple relative à
UIAccelerometerDelegate, vous verrez que la méthode
didAccelerate est appelée lorsque de nouvelles données issues de l'accéléromètre sont disponibles. Définissez cette méthode comme suit :
Code : Objective-C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | - (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
if (fabsf(acceleration.x) > 1.5 || fabsf(acceleration.y) > 1.5 || fabsf(acceleration.z) > 1.5)
{
[mouvement setText:@"J'ai détecté une secousse"];
if (temporisation == 0)
temporisation = 1;
}
x.text=[NSString stringWithFormat:@"%@ %f",@"X =",acceleration.x];
y.text=[NSString stringWithFormat:@"%@ %f",@"Y =",acceleration.y];
z.text=[NSString stringWithFormat:@"%@ %f",@"Z =",acceleration.z];
if (temporisation > 0)
temporisation++;
if (temporisation == 30)
{
[mouvement setText:@"Le device est calme"];
temporisation = 0;
}
}
|
N'ayez crainte, il n'y a rien de bien méchant dans cette méthode !
Si le gabarit de la méthode vous semble compliqué, sachez qu'il a été automatiquement proposé par Xcode dès la saisie du mot
accelerometer, comme le montre la figure suivante.
Les accélérations selon les axes X, Y et Z sont accessibles dans les propriétés
x,
y et
z de l'objet
acceleration. L'instruction de la ligne 3 teste si l'accélération du device est supérieure à 1,5 selon un des axes :
Code : Objective-C | if (fabsf(acceleration.x) > 1.5 || fabsf(acceleration.y) > 1.5 || fabsf(acceleration.z) > 1.5)
|
Dans ce cas, le device a été agité, et un texte est affiché en conséquence dans le
Label mouvement :
Code : Objective-C | [mouvement setText:@"J'ai détecté une secousse"];
|
Remarquez l'utilisation de la fonction fabsf() qui renvoie la valeur absolue de son argument. En d'autres termes, l'argument privé de son signe. L'accélération peut en effet être négative. En la privant de son signe, il est plus facile de tester si elle dépasse une certaine limite et ainsi décréter qu'il y a eu une agitation du device.
Rappelez-vous : la mise à jour des quatre
Labels se fait 10 fois par seconde. Il est donc nécessaire de mettre en place un artifice pour que le texte « J'ai détecté une secousse » reste affiché plus longtemps, sans quoi il sera pratiquement impossible de le voir. C'est le rôle des deux instructions qui suivent :
Code : Objective-C | if (temporisation == 0)
temporisation = 1;
|
La variable
temporisation vaut 0 par défaut. Elle indique que le device n'a pas été agité. Elle est mise à 1 pour indiquer que le device vient d'être agité.
Les lignes 10 à 12 affichent les valeurs des accélérations dans les labels
x,
y et
z :
Code : Objective-C | x.text=[NSString stringWithFormat:@"%@ %f",@"X =",acceleration.x];
y.text=[NSString stringWithFormat:@"%@ %f",@"Y =",acceleration.y];
z.text=[NSString stringWithFormat:@"%@ %f",@"Z =",acceleration.z];
|
Il n'y a pas grand-chose à dire au sujet de ces instructions. D'une façon très classique, la méthode
stringWithFormat est utilisée pour concaténer deux éléments (ici, un texte et un flottant) et les convertir en un
NSString.
Le bloc d'instructions suivant est plus intéressant. C'est lui qui se charge d'afficher le texte « J'ai détecté une secousse » pendant trois secondes.
Si la variable temporisation est supérieure à 0, on l'incrémente :
Code : Objective-C | if (temporisation > 0)
temporisation++;
|
Si elle a pour valeur 30, ou en d'autres termes, si elle est passée une trentaine de fois par ce code (28 exactement), cela signifie qu'environ 3 secondes se sont écoulées depuis l'affichage du texte « J'ai détecté une secousse » dans le
Label :
Code : Objective-C
Dans ce cas, le texte « Le device est calme » est affiché dans ce même
Label et la variable
temporisation est mise à 0, en attendant que le device soit agité une nouvelle fois :
Code : Objective-C | {
[mouvement setText:@"Le device est calme"];
temporisation = 0;
}
|
Pour que ce code fonctionne, deux petites lignes doivent être ajoutées.
La variable
temporisation doit être initialisée à 0 dans la méthode
viewDidLoad :
Code : Objective-C | - (void)viewDidLoad
{
...
temporisation = 0;
...
}
|
La variable
temporisation doit être déclarée dans le fichier d'en-têtes :
Code : Objective-C | @interface accelerometreViewController : UIViewController <UIAccelerometerDelegate>
{
...
int temporisation;
}
|
Ça y est, l'application est entièrement fonctionnelle. Vous pouvez la lancer (pas dans le simulateur, évidemment !). La figure suivante représente ce que j'ai obtenu.
Cette application se trouve dans le dossier
accelerometre.
ViewController.h
Secret (cliquez pour afficher)
Code : Objective-C 1
2
3
4
5
6
7
8
9
10
11
12
13 | #import <UIKit/UIKit.h>
@interface ViewController : UIViewController <UIAccelerometerDelegate>
{
int temporisation;
}
@property (weak, nonatomic) IBOutlet UILabel *x;
@property (weak, nonatomic) IBOutlet UILabel *y;
@property (weak, nonatomic) IBOutlet UILabel *z;
@property (weak, nonatomic) IBOutlet UILabel *mouvement;
@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
74
75
76
77
78
79
80
81
82
83
84
85
86
87 | #import "ViewController.h"
@implementation ViewController
@synthesize x;
@synthesize y;
@synthesize z;
@synthesize mouvement;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:@"gyro.jpg"]];
UIAccelerometer *testAccel = [UIAccelerometer sharedAccelerometer];
testAccel.delegate = self;
testAccel.updateInterval = 0.1f;
temporisation = 0;
[mouvement setText:@"Le device est calme"];
}
- (void)viewDidUnload
{
[self setX:nil];
[self setY:nil];
[self setZ:nil];
[self setMouvement:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
if (fabsf(acceleration.x) > 1.5 || fabsf(acceleration.y) > 1.5 || fabsf(acceleration.z) > 1.5)
{
[mouvement setText:@"J'ai détecté une secousse"];
if (temporisation == 0)
temporisation = 1;
}
x.text=[NSString stringWithFormat:@"%@ %f",@"X =",acceleration.x];
y.text=[NSString stringWithFormat:@"%@ %f",@"Y =",acceleration.y];
z.text=[NSString stringWithFormat:@"%@ %f",@"Z =",acceleration.z];
if (temporisation > 0)
temporisation++;
if (temporisation == 30)
{
[mouvement setText:@"Le device est calme"];
temporisation = 0;
}
}
- (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
|