Vous êtes sur la page 1sur 514

Sauf mention contraire, le contenu de cet ouvrage est publi sous la licence :

Creative Commons BY-NC-SA 2.0


La copie de cet ouvrage est autorise sous rserve du respect des conditions de la licence
Texte complet de la licence disponible sur : http://creativecommons.org/licenses/by-nc-sa/2.0/fr/
Simple IT 2012 - ISBN : 979-10-90085-06-0

Avant-propos

es tlphones mobiles sont sans conteste la plus grande rvolution technologique


que l'on ait connue ces dernires annes. Trs vite, ils ont modi nos habitudes
et sont devenus indispensables pour beaucoup d'entre nous.
Tout a commenc en janvier 2007, San Francisco. Notre regrett Steve Jobs prsentait
alors le premier iPhone pendant le salon professionnel Macworld. Cet appareil extraordinaire regroupait un combin GSM, un assistant personnel, un baladeur compatible
MP3 et une visionneuse multimdia ! Le design trs soign de l'iPhone et sa prise en
main immdiate ont immdiatement sduit le public. Et depuis, cet engouement n'a
cess de progresser. Il faut bien dire qu'aujourd'hui, avec plus de 500 000 applications
disponibles sur l'App Store, les possibilits de l'iPhone ont de quoi donner le vertige.
Trois ans plus tard, en janvier 2010, toujours San Francisco, Steve Jobs prsentait
la tablette iPad 1. L encore, le public a t trs vite sduit par ce  gros iPhone sans
tlphone  ! Aujourd'hui, c'est--dire deux ans plus tard, l'App Store propose plus de
140 000 applications pour iPad.
Si vous aussi, vous voulez faire partie de cette grande famille de dveloppeurs pour
iPhone, iPad et iPod Touch, vous avez le bon ouvrage entre les mains ! Que vous soyez
un programmeur dbutant ou conrm, je vous montrerai au l des pages comment
tirer parti des immenses possibilits de ces appareils. Rapidement, vous serez capables
de crer vos propres applications. . . avec une facilit dconcertante ! Lors de vos premiers pas, vous devrez faire preuve de patience pour bien intgrer les techniques de
programmation si spciques au monde Apple. Mais bien vite, vous verrez que ce code
qui pourrait passer pour barbare aux yeux d'un profane, n'a rien de bien compliqu et
revt mme une certaine  lgance . . .
Bienvenue dans le monde magique de la programmation iOS !

Qu'allez-vous apprendre en lisant ce livre ?


Le plan de ce livre a t conu pour faciliter votre dcouverte et votre apprentissage
de la programmation iOS. Voici le chemin que nous allons parcourir :
1. Tout ce qu'il faut savoir avant de commencer : cette partie introductive va
passer en revue tout ce dont vous aurez besoin pour pouvoir programmer, tant
i

CHAPITRE 0.

AVANT-PROPOS

au niveau matriel que logiciel. Vous y trouverez toutes sortes d'informations


pratiques qui vous permettront de dmarrer sereinement. Ensuite, vous ferez
vos dbuts en programmation Objective-C, avant de tester votre toute premire
application. Peu importe que vous ayez ou non un iPhone/iPad/iPod Touch pour
tester cette application : nous utiliserons le simulateur iOS.
2. Le langage Objective-C : cette partie est essentielle si vous dbutez en programmation Objective-C, et encore plus si vous dbutez en programmation tout
court. Elle va vous dvoiler les principaux mcanismes qu'il est bon d'avoir
l'esprit avant de commencer plonger dans le code. Aprs avoir dcouvert les
bases de l'Objective-C (instructions, variables, oprateurs, types, tests, boucles,
fonctions), vous en apprendrez un peu plus sur le ct objet du langage, et en
particulier sur les classes et les mthodes. Cette tape franchie, vous verrez comment dialoguer avec les mthodes des classes les plus courantes. Et pour terminer
en beaut, vous mettrez en pratique tout ce que vous avez appris pour dvelopper
un jeu de Mastermind.
3. Cration d'interfaces graphiques : dans cette partie, vous allez faire plus
ample connaissance avec Interface Builder et dcouvrir ses immenses possibilits
pour crer des interfaces graphiques volues. Au l des pages, vous apprendrez
mettre en place des fentres, des vues et des contrles et les relier au code pour
pouvoir dialoguer avec eux. Vous verrez galement comment insrer des contrles
dans une vue en faisant abstraction d'Interface Builder, c'est--dire en utilisant
uniquement des instructions Objective-C. Tout ce que vous avez appris dans cette
partie sera mis en pratique en dveloppant une application qui facilite l'achage
de vos pages Web prfres.
4. Plus loin avec iOS 5 : Arrivs ce point dans la lecture du livre, vous savez
crer de petites applications iOS 5. Il est temps de passer la vitesse suprieure
en abordant des sujets qui sont chers tous les utilisateurs d'iPhone, iPod Touch
et iPad : la golocalisation, la lecture et l'enregistrement audio, la lecture vido,
la prise de photos, l'utilisation de l'acclromtre et le jeu. Bien entendu, vous
exprimenterez tout ce que vous avez appris en dveloppant une application en
solo. Ici, vous dvelopperez un jeu qui met en pratique l'utilisation d'un timer, le
dplacement de sprites, le test de collisions, le toucher de l'cran, l'utilisation de
bruitages et d'une musique de fond.
5. Tester et publier ses applications : a y est, vous avez cr une application
qui a toutes les chances de devenir un best-seller et vous mourez d'envie de la
rendre disponible aux possesseurs d'iPhone, d'iPod Touch et d'iPad du monde
entier ? Cette partie va vous montrer comment procder ! Aprs avoir souscrit au
programme de dveloppement iOS, vous verrez comment tester vos applications
sur un ou plusieurs devices. Cette tape passe avec succs, je vous conseille de
tester votre application  en long et en large  pour vous assurer qu'elle fonctionne
parfaitement. Je vous montrerai alors comment la soumettre Apple, puis, aprs
acceptation, la rendre accessible travers l'App Store.
ii

COMMENT LIRE CE LIVRE ?

Comment lire ce livre ?


Suivez l'ordre des chapitres
Lisez ce livre comme on lit un roman. Il a t conu pour cela.
Contrairement beaucoup de livres techniques o il est courant de lire en diagonale et
de sauter certains chapitres, il est ici trs fortement recommand de suivre l'ordre du
cours, moins que vous ne soyez dj un peu expriments.

Pratiquez en mme temps


Pratiquez rgulirement. N'attendez pas d'avoir ni de lire ce livre pour allumer votre
ordinateur et faire vos propres essais.

Utilisez les codes web !


An de tirer parti du Site du Zro dont ce livre est issu, celui-ci vous propose ce qu'on
appelle des  codes web . Ce sont des codes six chires saisir sur une page du Site
du Zro pour tre automatiquement redirig vers un site web sans avoir en recopier
l'adresse.
Pour utiliser les codes web, rendez-vous sur la page suivante 1 :
http://www.siteduzero.com/codeweb.html

Un formulaire vous invite rentrer votre code web. Faites un premier essai avec le code
ci-dessous
:


Tester
le
code
web
B
Code web : 123456


Ces codes web ont deux intrts :
 ils vous redirigent vers les sites web prsents tout au long du cours, vous permettant
ainsi d'obtenir les logiciels dans leur toute dernire version ;
 ils vous permettent de tlcharger les codes sources inclus dans ce livre, ce qui vous
vitera d'avoir recopier certains programmes un peu longs.
Ce systme de redirection nous permet de tenir jour le livre que vous avez entre les
mains sans que vous ayez besoin d'acheter systmatiquement chaque nouvelle dition.
Si un site web change d'adresse, nous modierons la redirection mais le code web
utiliser restera le mme. Si un site web disparat, nous vous redirigerons vers une page
du Site du Zro expliquant ce qui s'est pass et vous proposant une alternative.
En clair, c'est un moyen de nous assurer de la prennit de cet ouvrage sans que vous
ayez faire quoi que ce soit !
1. Vous pouvez aussi utiliser le formulaire de recherche du Site du Zro, section  Code web .

iii

CHAPITRE 0.

AVANT-PROPOS

Remerciements
crire un livre demande beaucoup d'nergie, de volont et de persvrance. C'est aussi
le travail de toute une quipe et je tiens remercier tous ceux et toutes celles qui m'ont
accompagn dans cette entreprise :
 Mathieu Nebra et Pierre Dubuc qui ont cru en ce projet et qui m'ont donn l'opportunit de le raliser ;
 Jonathan Baudoin qui a su me guider d'une main d'expert tout au long du processus
d'criture ;
 l'quipe de Simple IT et la communaut du Site du Zro, qui m'ont permis de peauner et parfois de donner une nouvelle orientation ce projet ;
 et enn mon pouse et mes enfants qui ne m'ont pas beaucoup vu pendant les
quelques mois ncessaires la mise au point du tutoriel puis du livre.
Et maintenant que mon  bb  a vu le jour, j'espre que vous aimerez son contenu
et que vous y apprendrez quelques celles. Je vous souhaite une bonne lecture et vous
dis bientt sur le Site du Zro !

iv

Sommaire
Avant-propos

I Tout ce qu'il faut savoir avant de commencer

1 L'quipement du codeur

Qu'allez-vous apprendre en lisant ce livre ? . . . . . . . . . . . . . . . . . . . . i


Comment lire ce livre ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iii
Remerciements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iv

De quel ordinateur s'quiper ? . . . .


Une brve histoire d'Apple . . . . .
Et la programmation dans tout a ?
Les logiciels ncessaires . . . . . . .

2 Un premier dveloppement

Cration de l'application . . . . . .
Ajout des contrles sur l'interface .
Liaison des contrles au code . . .
criture du code . . . . . . . . . .
Construction et excution . . . . .

.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

3 Le simulateur iOS

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

. 4
. 6
. 10
. 12
.
.
.
.
.

15

16
19
22
25
27

31

Les bases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Simuler les gestuelles et les actions de l'utilisateur . . . . . . . . . . . . . . . 33
v

SOMMAIRE

Quelques pratiques connatre . . . . . . . . . . . . . . . . . . . . . . . . . . 35

II Le langage Objective-C

39

4 Les bases de l'Objective-C

41

Instructions . . . . . . . . . . . . .
Variables, constantes et oprateurs
Commentaires . . . . . . . . . . . .
Types de donnes . . . . . . . . . .
Les pointeurs . . . . . . . . . . . .

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

43
44
52
52
54

5 Conditions, boucles et fonctions

61

6 La programmation oriente objet

75

Conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
Boucles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
Fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
Qu'est-ce que la programmation oriente objet ?
Dnir une classe . . . . . . . . . . . . . . . . . .
Dnir des mthodes . . . . . . . . . . . . . . . .
Appeler des mthodes . . . . . . . . . . . . . . .

.
.
.
.

7 Les principaux objets utiliss en Objective-C

Chanes de caractres
Nombres . . . . . . . .
Dates et heures . . . .
Tableaux . . . . . . .
Dictionnaires . . . . .
Ensembles . . . . . . .

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

8 TP : Un jeu de Mastermind

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

76
79
85
86

95

96
99
100
108
113
116
119

Instructions pour raliser le TP . . . . . . . . . . . . . . . . . . . . . . . . . . 120


Correction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121

vi

SOMMAIRE

III Cration d'interfaces graphiques

139

9 Fentres, vues et contrles

141

Cration d'une application multivues . . . . . . . . . . .


Insrer un contrle dans une application . . . . . . . . .
Positionner, aligner et redimensionner un contrle vue
Un aperu des contrles disponibles . . . . . . . . . . .
Les volets Attributs et Taille . . . . . . . . . . . . . .

10 Les contrles qui achent des donnes (1/2)

Acher du texte non modiable .


Saisir du texte sur une ligne . . . .
Saisir du texte sur plusieurs lignes
Acher une image . . . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

11 Les contrles qui achent des donnes (2/2)

Acher du contenu Web . . . . . . . . . . . . . . . . . . . . . . . . . . . .


Acher une carte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Quand le contenu dpasse la taille du contrle, de la vue ou de la fentre .
Demander son avis l'utilisateur . . . . . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

142
145
146
148
151

155

156
157
159
159

175

176
177
183
186

12 Les informations tabulaires

197

13 Les contrles d'action

223

Listes d'informations sur une colonne . . . . . . . . . . . . . . . . . . . . . . . 198


Listes d'informations sur une ou plusieurs colonnes . . . . . . . . . . . . . . . 211
Slection d'une date dans un contrle spcialis . . . . . . . . . . . . . . . . . 218
Boutons . . . . . . . .
Segmented Control .
Zones de texte . . . .
Curseurs . . . . . . . .
Interrupteurs . . . . .
Contrles de page . . .

.
.
.
.
.
.

14 Barres et tabulations

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

224
226
230
234
235
237

247

Applications multivues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248


vii

SOMMAIRE

Barre d'outils . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251


Barre de recherche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255
Gestion simultane de deux vues sur un iPad . . . . . . . . . . . . . . . . . . 262
15 Insertion de contrles avec le code

Le code complet . . . . . . . . . . . . . .
Achage d'un Label . . . . . . . . . . . .
Achage d'un Round Rect Button . . . .
Achage d'un Text Field . . . . . . . .
Achage d'un rectangle de couleur rouge
Achage d'une image . . . . . . . . . . .

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

271

272
274
276
277
278
278

16 TP : Un navigateur Web trs cibl

281

IV Plus loin avec iOS 5

297

17 Golocalisation

299

18 Multimdia : le son

321

19 Multimdia : l'image

357

20 Acclromtre

375

21 Un jeu de casse-briques

387

Principe du TP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282
Correction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283

Longitude et latitude . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 300


Vitesse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308
Golocalisation inverse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312

Jouer des lments audio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322


Enregistrement audio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
Jouer des lments vido . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358
Prendre des photos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366
Mise en place de l'application . . . . . . . . . . . . . . . . . . . . . . . . . . . 376
criture du code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378

viii

SOMMAIRE

Dnition de l'interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388


Immersion dans le code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392
Le code de l'application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401
22 TP : Capturez les vers

407

V Tester et publier ses applications

427

23 Gestion des matriels et des identits numriques

429

Principe du TP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408
Solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410

Dboguer une application . . . . . . . . . . . .


Souscrire au programme de dveloppement iOS
Certicats et prols d'approvisionnement . . .
Travailler sur un device . . . . . . . . . . . . .

24 Proposer une application sur l'App Store

Prparation prliminaire . . . . . . . . . . .
Conguration de iTunes Connect . . . . .
Validation et soumission d'une application .
Gagner de l'argent avec une application . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

430
432
438
448

453

454
464
470
472

ix

SOMMAIRE

Premire partie
Tout ce qu'il faut savoir avant de
commencer

Chapitre

L'quipement du codeur
Dicult :

a y est, vous tes prts franchir le pas et dvelopper des applications pour les
priphriques mobiles Apple ? Vous devez certainement vous demander si cela est
possible et si vous y arriverez.
Rien n'est impossible ! Surtout que je vais vous accompagner tout au long de votre apprentissage. Peu importe si vous n'avez jamais utilis de Mac ou si vous n'avez aucune
exprience en programmation. Avec de la volont et arms de ce livre, vous vous en sortirez
haut la main.
Si vous tes prts tenter l'aventure, voyons de quel matriel vous aurez besoin.

CHAPITRE 1.

L'QUIPEMENT DU CODEUR

De quel ordinateur s'quiper ?


Comment a, de quel ordinateur s'quiper ? J'ai dj un PC et j'en suis satisfait ! Pourquoi est-ce que je devrais investir dans un nouveau matriel ?

Eh bien, je suis dsol de vous l'apprendre, mais les dveloppements pour iPhone, iPad
et iPod Touch se font presque exclusivement sur Mac. Et ce n'est pas tout ! Le Mac
doit :
1. tre quip d'un processeur Intel ;
2. possder au moins 1 gigaoctet (1 Go) de mmoire vive ;
3. utiliser le systme d'exploitation Mac OS X Lion, Snow Leopard ou Leopard ;
4. disposer d'un port USB libre et/ou d'une connexion wi an de connecter votre
iPhone/iPod Touch/iPad l'ordinateur et de tester vos applications.
Presque exclusivement sur un Mac ? Des prcisions s'il vous plat ?

Il est galement possible de dvelopper des applications pour les produits Apple en
utilisant un ordinateur fonctionnant sous Windows ou Linux, mais ce n'est (vraiment)
pas la voie la plus simple, ni bien videmment celle recommande par Apple. Ce livre
s'intressera uniquement la mthode de dveloppement traditionnelle : sur un Mac,
via l'application Xcode.
Si vous possdez dj un Mac, je vais vous montrer comment savoir s'il est quip en
consquence : cliquez sur la pomme dans le Finder et slectionnez propos de ce
Mac dans le menu. la gure 1.1 par exemple, le Mac est quip d'un processeur Intel
Core 2 Duo et utilise le systme OS X 10.6.7, donc Snow Leopard.
Les trois dernires versions du systme d'exploitation Mac OS X sont les suivantes :
 10.7.x : Lion ;
 10.6.x : Snow Leopard ;
 10.5.x : Leopard.
Si vous devez vous quiper, allez faire un tour sur l'Apple Store. Tous les Mac vendus
dans le Store peuvent tre utiliss. Selon votre budget, vous choisirez un Mac Mini, un
MacBook, un MacBook Air, un MacBook Pro ou un iMac.
Si votre budget est limit, rabattez-vous sur une machine reconditionne. Vous y trouverez des Mac tests et agrs par Apple. Sous garantie pendant un an, les machines
proposes sont un prix sensiblement infrieur celui du neuf et (sauf exception) dans
un excellent tat !
Dans la mesure du possible, investissez dans un cran large de 22 ou 24 pouces. Comme
vous le verrez dans ce livre, l'environnement de dveloppement est l'aise sur un grand
4

DE QUEL ORDINATEUR S'QUIPER ?

Figure 1.1  Quelques informations propos du Mac

cran, et un 22 pouces n'est vraiment pas un luxe ! Si vous tes dj quips d'un cran
pour PC, vous pourrez le connecter sur votre Mac, condition que sa connexion soit
de type DVI (gure 1.2).

Figure 1.2  Une prise DVI

J'entends dj bon nombre d'entre vous se plaindre :  mon cran n'a qu'un connecteur
VGA ! Est-ce que je dois acheter un nouvel cran ?  Non, rassurez-vous, il vous sut
d'acheter un adaptateur VGA/DVI (gure 1.3). Pour quelques euros, vous pourrez
connecter votre Mac sur votre cran VGA.

Figure 1.3  Un adaptateur VGA/DVI

Pour les plus ambitieux d'entre vous, sachez qu'il est possible de connecter deux crans
sur tous les Mac rcents. vous de trouver les adaptateurs qui conviennent, comme
5

CHAPITRE 1.

L'QUIPEMENT DU CODEUR

par exemple un Mini DisplayPort/VGA (gure 1.4).

Figure 1.4  gauche un Mini DisplayPort/VGA et droite un Mini DisplayPort/DVI

Un autre matriel est-il ncessaire ?


Je vais encore jouer les rabat-joie : il ne sut pas d'tre quip d'un Mac pour crire
des applications destines aux appareils mobiles Apple. Vous devez galement possder
un iPhone, un iPod Touch et/ou un iPad. Ou encore mieux, les trois !
En eet, si l'environnement de dveloppement est en mesure de simuler le fonctionnement de ces trois appareils, le comportement des applications est cependant biais
car elles ne disposent pas des mmes ressources (mmoire et processeur) si elles sont
excutes sur un Mac ou sur un device (entendez par l un iPhone, un iPad ou un
iPod Touch).
Retenez bien ce terme de device, je l'utiliserai par la suite pour dsigner un
iPhone, un iPad, un iPod Touch, ou mme les trois en mme temps.

Une bonne nouvelle : les iPod Touch et les iPad sont galement disponibles en version
reconditionne ! Vous pourrez faire de substantielles conomies en vous rendant sur
ces pages. Par cet intermdiaire, je me suis quip d'un iPad et d'un iPod Touch
reconditionns, et je dois dire que je m'en flicite tous les jours. :-)

Une brve histoire d'Apple


l'origine d'Apple, deux amis : Steve Wozniak et Steve Jobs. Le premier est un lectronicien et un programmeur de gnie. Le deuxime est un visionnaire qui saura imposer
la marque la pomme en lui confrant une simplicit d'utilisation et une ligne uniques.
Steve Jobs est l'instigateur de cinq volutions majeures dans le monde de l'informatique
personnelle :
 l'Apple II ;
 le Macintosh ;
 l'iPod ;
 l'iPhone ;
 l'iPad.
6

UNE BRVE HISTOIRE D'APPLE

C'est courant 1975 que nat l'Apple I dans le garage de Steve Jobs. Rencontrant un succs mitig mais susant, il apporte susamment de capitaux pour que Steve Wozniak
se consacre temps plein son digne successeur, l'Apple II. Cette machine rvolutionnaire conquiert un large public grce ses innovations majeures, notamment un
achage texte et graphique, un interprteur BASIC, le tableur VisiCalc et un lecteur
de disquettes !
Dbut 1984, le grand public dcouvre le premier modle de Macintosh. C'est encore
Steve Jobs que l'on doit ce beau succs commercial. Son design innovant, sa compacit, son cran graphique de grande qualit, sa simplicit d'utilisation et. . . sa souris
rvolutionnent l'utilisation de l'ordinateur. Le succs est immdiat et perdure depuis
lors.
Mais l'aventure ne s'arrte pas l : en 2001 nat l'iPod, en 2007 l'iPhone et en 2010
l'iPad. Bien sr, l'iPod n'est pas le premier baladeur MP3, l'iPhone n'est pas le premier
tlphone cellulaire et l'iPad n'est pas la premire tablette tactile. Par contre, ces trois
priphriques sont vraiment simples utiliser, et c'est ce qui fera leur succs. Une fois
encore, Steve Jobs a su airer le march et adapter ce qui a fait le succs d'Apple : la
simplicit d'utilisation et la ligne esthtique.
Aujourd'hui, Steve Jobs n'est plus avec nous, mais son empreinte demeure indlbile
dans la galaxie Apple !

Les iPhone, iPod Touch et iPad


L'iPhone

Les iPhone (gure 1.5) sont en tout point comparables aux iPod Touch, si ce n'est
qu'ils permettent de tlphoner. Vous pouvez donc les utiliser pour :
 joindre un correspondant par tlphone ;
 couter de la musique ;
 prendre des photos ( partir de l'iPhone 3) ;
 joindre un autre utilisateur d'iPhone/iPod Touch/iPad en visioconfrence ( partir
de l'iPhone 4) ;
 excuter les applications crites pour les iPhone.
Avec l'assistant vocal des iPhone 4S, vous pouvez dicter des ordres votre
tlphone. Ainsi, vous pouvez prendre un rendez-vous, demander la mto,
ajouter une alarme, etc. . . . en parlant simplement votre tlphone. Attention, cet assistant n'est disponible que sur les modles 4S.

CHAPITRE 1.

L'QUIPEMENT DU CODEUR

Figure 1.5  L'iPhone


iPod Touch

Les iPod Touch (gure 1.6) sont quips d'un cran tactile de 3,5 pouces de diagonale.
Ils peuvent tre utiliss pour :
 couter de la musique ;
 prendre des photos ( partir de l'iPod Touch 4) ;
 joindre un autre utilisateur d'iPhone/iPod Touch/iPad en visioconfrence ( partir
de l'iPod Touch 4) ;
 excuter les applications crites pour les iPhone.

Figure 1.6  L'iPod Touch

UNE BRVE HISTOIRE D'APPLE

iPad

Les iPad (gure 1.7) sont en gros des iPod Touch un peu plus grands. Ils peuvent donc
tre utiliss pour :
 couter de la musique ;
 prendre des photos ( partir de l'iPad 2) ;
 joindre un autre utilisateur d'iPhone/iPod Touch/iPad en visioconfrence ( partir
de l'iPad 2) ;
 excuter toutes les applications crites pour les iPhone ainsi que les applications
propres l'iPad.

Figure 1.7  L'iPad

La grande taille de l'achage les rend galement plus agrables que les iPod Touch ou
les iPhone pour surfer sur le Web et lire des e-books et autres chiers PDF.
Vous avez maintenant une ide des possibilits oertes par les appareils mobiles Apple.
Une question cruelle va se poser vous : de quel(s) appareil(s) devez-vous vous quiper ?
Le mieux serait d'avoir un iPhone, un iPod Touch et un iPad. Vous pourriez ainsi
dvelopper pour ces trois priphriques et toucher un vaste public. Notez cependant
que les dirences entre l'iPod Touch et l'iPhone sont trs rduites : grossirement, le
premier est quivalent au second, except qu'il ne peut pas tre utilis pour tlphoner.
Un bon choix consiste donc acheter :
 un iPhone et un iPad si vous avez l'utilit d'un tlphone mobile ;
 un iPod Touch et un iPad si vous n'avez pas l'utilit d'un tlphone mobile ;
 un iPhone ou un iPod Touch si vos applications ne sont pas destines aux tablettes
iPad.
9

CHAPITRE 1.

L'QUIPEMENT DU CODEUR

Limitations des appareils mobiles Apple


Les appareils mobiles Apple sont limits par :
 la taille de l'achage :
 480 x 320 pixels : iPod Touch 3 et iPhone 3 ;
 960 x 640 pixels : iPod Touch 4 et iPhone 4 ;
 1024 x 768 pixels : iPad 1 et 2 ;
 2048 x 1536 pixels : iPad 3 ;
 la quantit de mmoire vive disponible :
 128 Mo : iPod Touch 3 avec 8 Go de mmoire ash ;
 256 Mo : iPod Touch 3 avec plus de 8 Go de mmoire ash, iPod Touch 4, iPhone
3 et iPad 1 ;
 512 Mo : iPhone 4 et iPad 2 ;
 dans une moindre mesure, le type et la vitesse du processeur.
La taille de l'achage est un facteur dterminant. Elle conditionnera la mise en page
de vos applications et devra s'adapter aux tailles caractristiques des dirents appareils mobiles. La quantit de mmoire vive est assez limite. C'est pour cela qu'il est
absolument ncessaire de tester une application sur un priphrique physique avant
de la rendre disponible sur l'Apple Store.
Le type et la vitesse du processeur n'inuent qu'assez peu sur la vitesse d'excution
des applications. Ils ne seront pris en compte que dans le cas de jeux manipulant un
grand nombre d'lments graphiques.

Et la programmation dans tout a ?


Qu'est-ce qu'un programme ?
Les ordinateurs, les tlphones, les tablettes graphiques et, d'une certaine manire,
tous les appareils numriques, utilisent des programmes (appels aussi applications)
pour accomplir des tches bien prcises. Ainsi par exemple, lorsque vous dmarrez
votre traitement de texte, votre navigateur Web ou votre messagerie, vous utilisez
un programme. Autour de ces programmes, un  super programme , appel systme
d'exploitation, joue le rle de chef d'orchestre et permet aux applications d'accder au
matriel sur lequel elles s'excutent. On dit qu'il sert d'interface entre le matriel et les
programmes. titre d'exemple, Microsoft Windows et Mac OS X sont des systmes
d'exploitation.
Selon le matriel et le systme d'exploitation utiliss, les applications sont crites en
utilisant un ou plusieurs langages de programmation. Les iPhone, iPod Touch et iPad
sont orchestrs par un systme d'exploitation identique. Pour crire des applications
destines ce systme, un seul langage de programmation peut tre utilis : ObjectiveC.
10

ET LA PROGRAMMATION DANS TOUT A ?

Connaissances pralables ncessaires pour programmer


Vous tes en train de lire un Livre du Zro, et ce titre, et pour ne pas droger la
rgle, aucune connaissance pralable n'est ncessaire ! Ceci tant dit, si vous avez dj
une premire exprience de la programmation oriente objet ou du langage ObjectiveC, ce sera un vrai plus : vous comprendrez trs rapidement bon nombre de notions
qui seront voques ici et vous serez trs vite capables de passer la pratique. Si vous
n'avez jamais programm, ne vous en faites surtout pas ! Je serai votre guide tout au
long de votre apprentissage. Pour peu que vous ayez un peu de temps, d'intrt, de
passion et de persvrance, vous progresserez trs vite.

Langages, API et systme


Tout au long de ce tutoriel, nous allons souvent parler d'Objective-C, de Cocoa
Touch et d'iOS. Il est temps pour moi de vous prsenter ces termes.
 Objective-C est le langage de programmation utilis pour dvelopper des applications pour iPhone, iPod Touch et iPad. Il s'agit d'un langage hrit du langage C,
c'est--dire que l'Objective-C emprunte au C bon nombre de choses.
 Cocoa Touch est une API 1 ddie l'criture d'applications pour iPhone, iPod
Touch et iPad. Une API est constitue d'un ensemble de programmes pr-crits
(classes et mthodes dans le jargon des spcialistes). Cocoa Touch ne droge pas la
rgle ; elle est spciquement dveloppe pour les devices Apple. Elle est accessible
travers Xcode, le logiciel de dveloppement que nous utiliserons.
 iOS est le systme d'exploitation des iPhone/iPod Touch/iPad.
Vous trouverez la gure 1.8 un schma pour vous aider visualiser tout ce petit
monde.

Figure 1.8  Nous aurons besoin du langage Objective-C et de Cocoa Touch pour

dvelopper nos applications iOS


1.

Application Programming Interface ou, en franais, interface de programmation.

11

CHAPITRE 1.

L'QUIPEMENT DU CODEUR

Combien de temps me faudra-t-il pour crire ma premire application ?

Les rponses cette question sont multiples. Si tous les logiciels ncessaires sont installs et si vous voulez juste crer votre premire application sans vraiment comprendre
ce que vous faites, dix minutes sont susantes !
Si rien n'est encore install (je suppose quand mme que vous avez un Mac sous la
main), comptez trois quatre heures pour installer le logiciel et mettre au point une
application qui ache un texte sur votre device.
Je vous conseille cependant de ne pas compter le temps pass : vous vous lancez dans une
grande aventure. Il vous faudra du temps (beaucoup de temps mme) pour comprendre
les mcanismes de la programmation Objective-C, mais cela en vaut la peine ! Une fois
les mcanismes de base assimils, vous pourrez raliser tout ce qui vous vient en tte. . .

Les logiciels ncessaires


Xcode sur votre Mac
Xcode est le programme que vous utiliserez pour dvelopper vos applications. La version
utilise dans ce tutoriel est la 4.2 (sous OS X Lion 10.7.2). Si vous utilisez une autre
version, quelques dtails direront, mais la plupart de ce qui sera dit restera valable.
Par dfaut, Xcode est normalement dj install sur votre Mac. Pour vous en assurer,
cliquez sur l'icne du Finder, l'extrme gauche du dock. Cette action ouvre une fentre
dans laquelle sont achs vos principaux dossiers, comme le montre la gure 1.9.

Figure 1.9  Achage des principaux dossiers du Mac

12

LES LOGICIELS NCESSAIRES

Dans le volet de gauche, sous APPAREILS, cliquez sur Macintosh HD. Dans le volet de
droite, double-cliquez sur Developper, sur Applications, puis sur Xcode. Une bote
de dialogue est alors ache, comme la gure 1.10.

Figure 1.10  Une bote de dialogue Xcode s'ache

La version du logiciel est ache juste en dessous du titre  Welcome to Xcode . Ici,
il s'agit de la version 3.2.6. Si votre version de Xcode n'est pas au moins gale la
4.2, je vous conseille vivement de tlcharger puis d'installer la toute dernire version
disponible. Pour cela, vous devez rejoindre la communaut des dveloppeurs Apple.
Rassurez-vous, cette opration est entirement gratuite. Connectez-vous sur la page
d'enregistrement d'Apple, cliquez sur Get Started et suivez la procdure indique
pour rejoindre la communaut des dveloppeurs.


Rejoindre
la
communaut
B
Code web : 403043


Si vous ne savez pas comment utiliser les codes web, je vous renvoie la page
iii de l'avant-propos de ce livre, vous trouverez la marche suivre.

Une fois enregistrs, connectez-vous sur la page de tlchargement de Xcode, cliquez


sur Log in et connectez-vous en utilisant votre identiant Apple ID.


Tlcharger
Xcode
B
Code web : 270285


Attention, toutes les versions de Xcode ne sont pas compatibles avec toutes les versions
du systme d'exploitation OS X. vous d'installer la version approprie :
13

CHAPITRE 1.

L'QUIPEMENT DU CODEUR

 Leopard : Xcode 3.1 ;


 Snow Leopard : Xcode 3.2 ou 4.0 ;
 Lion : Xcode 4.2.
Et surtout, armez-vous de patience : le chier tlcharger pse quelque 4 Go !
La version 4.0 de Xcode est disponible pour les membres du programme de
dveloppement (99 dollars par an), mais galement sur l'App Store pour la
modique somme de 3,99 euros. Quant la version 4.1 de Xcode, elle est
disponible gratuitement sur l'App Store.

Installation de Xcode
Dans l'exemple qui va suivre, je me suis bas sur Xcode 4.2 sous OS X Lion.
Si vous installez une autre version, il se peut que vous n'ayez pas exactement
la mme chose que moi, mais le principe reste le mme.

Une fois Xcode tlcharg, une icne d'installation est ache dans le dock, comme
la gure 1.11.

Figure 1.11  L'icne d'installation de Xcode apparat dans le dock

Cliquez sur l'icne Install Xcode. Cette action ouvre la fentre Install Xcode. Cliquez sur Install, sur Agree, entrez votre nom et votre mot de passe puis patientez
jusqu' la complte installation du programme. Une fois l'installation termine, l'icne
Install Xcode du dock se transforme en Xcode. Il sut de cliquer dessus pour accder
Xcode.

En rsum
 Les dveloppements pour iPhone, iPod Touch et iPad se font sur un Mac quip d'un
processeur Intel.
 Pour dvelopper des applications pour iPhone, iPod Touch et iPad, vous utiliserez
l'application Xcode, normalement dj installe sur votre Mac. Si tel n'tait pas le
cas, vous pouvez tlcharger Xcode depuis le site pour dveloppeurs d'Apple.
 Pour utiliser la dernire version de l'application Xcode (4.2.x), le Mac doit utiliser
le systme d'exploitation OS X Lion ou suprieur.

14

Chapitre

Un premier dveloppement
Dicult :

e but de ce premier dveloppement est de vous faire prendre contact avec Xcode et
le langage Objective-C. N'essayez pas de comprendre tout ce qui va tre dit ici : cela
deviendra de plus en plus clair au fur et mesure de votre apprentissage.
Vous verrez, cette premire application sera vraiment trs basique. Un clic sur l'cran
remplacera un texte par un autre. a n'a l'air de rien dit comme a, mais ce n'est dj pas
si mal.

15

CHAPITRE 2.

UN PREMIER DVELOPPEMENT

Cration de l'application
Avant toute chose, il nous faut lancer Xcode, en cliquant par exemple sur l'icne prsente dans le dock (gure 2.1).

Figure 2.1  L'icne de Xcode dans le dock

La fentre Welcome

to Xcode

s'ache alors, comme la gure 2.2.

Figure 2.2  Fentre de lancement de Xcode

Nous allons ensuite crer un nouveau projet. Pour cela, rien de plus simple, il vous sut
de cliquer sur Create a new Xcode project. Une nouvelle bote de dialogue s'ache
(gure 2.3). Dans le volet de gauche, sous iOS, choisissez Application. Dans la partie
centrale de la bote de dialogue, choisissez Single View Application.
Cliquez sur Next, donnez le nom  premier  au projet, tapez  test  dans la zone
de texte Company Identifier, slectionnez iPhone dans la liste Device Family, et
cochez la case Include Unit Tests, comme indiqu la gure 2.4.
Cliquez sur Next et choisissez le dossier dans lequel le projet sera cr (gure 2.5), au
besoin en cliquant sur New Folder pour crer un nouveau dossier.
Cliquez sur Create. Le projet est alors cr et ouvert dans Xcode, comme la gure
2.6.
16

CRATION DE L'APPLICATION

Figure 2.3  Cration d'un nouveau projet dans Xcode

Figure 2.4  Les options du nouveau projet

17

CHAPITRE 2.

UN PREMIER DVELOPPEMENT

Figure 2.5  Il faut choisir l'emplacement du projet

Figure 2.6  Le projet est cr et ouvert

18

AJOUT DES CONTRLES SUR L'INTERFACE

Cette fentre va vous permettre de dnir l'allure de l'application, de saisir du code


Objective-C et de tester l'application. Pour l'instant, nous n'allons pas entrer dans les
dtails de la fentre de Xcode, cela ne ferait que vous embrouiller.
Vous vous demandez peut-tre pourquoi avoir choisi une application de type
Single View, ou encore pourquoi avoir tap  test  dans la zone de texte
Company Identifier. Ces deux questions resteront pour l'instant sans rponse. Plutt que de tout introduire en mme temps et de vous noyer sous
des dtails qui ne manqueraient pas de s'entremler dans votre tte, j'ai choisi
de ne pas rpondre pour l'instant ces deux questions. . . qui sont toutefois
bien lgitimes.

Ajout des contrles sur l'interface


La premire tape va consister dessiner ce que l'on souhaite voir s'acher sur l'cran
du device 1 . L'interface de Xcode est compose de plusieurs modules (diteur de code,
zone de dbogage, utilitaires, diteur d'interface, etc.). Chacun d'entre eux utilise un
ou plusieurs volets, accessibles partir de la zone de navigation ou de la barre d'outils.
Dans cette premire tape, vous allez utiliser Interface Builder pour construire la
partie visuelle de l'application. Pour ce faire, procdez selon les trois tapes suivantes
en vous aidant au besoin de la gure 2.7.
1. Dans la zone de navigation, cliquez sur MainStoryboard.storyboard (1) pour
accder Interface Builder.
2. Dans la barre d'outils, cliquez sur l'icne Hide or Show the utilites (2), audessus du libell View, pour rvler le volet des utilitaires.
3. Dans la partie infrieure du volet des utilitaires, cliquez sur l'icne Show the
Object library (3) pour acher la bibliothque d'objets. Cliquez si ncessaire
sur l'icne Icon View (4) pour acher plus de contrles dans la bibliothque
d'objets.
Glissez-dposez un contrle Label de la bibliothque d'objets dans la zone d'dition. Si
vous n'tes pas (encore) familiers avec cette opration, sachez qu'elle consiste cliquer
sur le contrle Label dans la bibliothque d'objets, maintenir le bouton gauche de
la souris enfonc, dplacer l'lment ainsi slectionn au-dessus de la zone d'dition
puis relcher le bouton de la souris, comme le montre la gure 2.8.
Glissez-dposez ensuite un contrle Round Rect Button (un bouton) de la bibliothque
d'objets dans la zone d'dition, comme indiqu la gure 2.9.
Vous allez maintenant modier le texte ach par dfaut dans le Label. Double-cliquez
sur celui-ci dans la zone d'dition, crivez  Cliquez sur le bouton  puis appuyez sur la
1. Je vous rappelle que device dsigne le priphrique sur lequel s'excutera l'application ; il peut
tout aussi bien s'agir d'un iPhone, d'un iPod Touch ou d'un iPad. Ici, la cible de l'application tant
un iPhone ou iPod Touch, device dsigne ces deux priphriques.

19

CHAPITRE 2.

UN PREMIER DVELOPPEMENT

Figure 2.7  Achage de la bibliothque d'objets

Figure 2.8  Glisser-dposer un contrle Label

20

AJOUT DES CONTRLES SUR L'INTERFACE

Figure 2.9  Le contrle Round

Rect Button

touche Entre de votre clavier. Faites de mme pour acher un texte sur le bouton :
double-cliquez sur le bouton, crivez  Cliquez ici  et appuyez sur la touche Entre .
La zone d'dition doit maintenant ressembler la gure 2.10.

Figure 2.10  La zone d'dition que vous devriez avoir

21

CHAPITRE 2.

UN PREMIER DVELOPPEMENT

Liaison des contrles au code


Cette application doit acher un texte dans le Label lorsque l'utilisateur clique sur le
bouton. Pour que le code Objective-C puisse agir sur les contrles dnis dans l'tape
prcdente, il faut relier les contrles au code.
Cliquez sur l'icne Show the Assistant editor, au-dessus du libell Editor, dans la
partie droite de la barre d'outils (gure 2.11). Cette action ache le code du chier
ViewController.h dans un volet vertical.

Figure 2.11  L'icne Show

the Assistant editor

Si votre cran n'est pas assez large pour visualiser la zone d'dition et le code, dsactivez la zone d'utilitaires en cliquant sur l'icne Hide or Show the Utilities, dans
la partie droite de la barre d'outils, au-dessus du libell View (gure 2.12).

Figure 2.12  L'icne Hide

or Show the Utilities

Le chier ViewController.h contient les dclarations relatives aux objets manipuls.


Dclarations, objets ? Je n'y comprends rien !

Les applications dveloppes avec Xcode sont composes de nombreux chiers. Certains
ont un nom qui se termine par .h, comme par exemple ViewController.h dans le cas
qui nous intresse. Ces chiers sont dits chiers d'en-ttes. Ils contiennent des instructions Objective-C qui permettent d'identier les objets (c'est--dire les contrles
dposs sur la zone d'dition depuis Interface Builder) utiliss dans l'application. Ces
instructions sont appeles dclarations.
Pour ajouter les dclarations ncessaires pour le Label, contrle-glissez-dposez le
contrle Label du volet d'dition dans le volet de code, juste au-dessus de la dernire
ligne (gure 2.13). Cette technique deviendra vite habituelle. Elle consiste :
1. placer le pointeur de la souris sur le contrle Label dans le volet d'dition ;
22

LIAISON DES CONTRLES AU CODE

2. maintenir la touche Ctrl de votre clavier enfonce ;


3. maintenir le bouton gauche de la souris enfonc et dplacer le contrle Label
du volet d'dition dans le volet de code, juste au-dessus de la ligne o apparat
l'instruction @end ;

4. relcher le bouton gauche de la souris ainsi que la touche Ctrl .

Figure 2.13  Un simple contrle-glisser-dposer permet d'ajouter des dclarations

dans le volet d'dition


Au relchement du bouton gauche de la souris, une bote de dialogue est ache. Tapez
 message  dans la zone de texte Name, comme la gure 2.14.

Figure 2.14  Une bote de dialogue s'ache au relchement du bouton de la souris

Cliquez sur Connect. Le code du chier ViewController.h devrait maintenant ressembler ceci :
1
2

# import < UIKit / UIKit .h >

23

CHAPITRE 2.

3
4
5
6
7

UN PREMIER DVELOPPEMENT

@interface ViewController : UIViewController


@property ( weak , nonatomic ) IBOutlet UILabel * message ;
@end

Passons quelques minutes sur ce code si vous le voulez bien.


La premire ligne, sur laquelle gure le mot import, fait rfrence tout ce dont
vous aurez besoin pour dvelopper une interface utilisateur pour priphrique iOS.
En ajoutant cette simple ligne au dbut de l'application, le code pourra acher sur
l'cran du device et rpondre aux gestuelles (appui, dplacement, rotation, etc.) des
utilisateurs.
La ligne 3, sur laquelle gure le mot interface, indique que l'application ViewController
est de type UIViewController :
1

@interface ViewController : UIViewController

La ligne 5, qui contient le mot property, indique le comportement de l'objet :


1

@property ( weak , nonatomic ) IBOutlet UILabel * message ;

Pour l'instant, ne vous proccupez pas des paramtres qui font suite au mot
interface. Ces paramtres sont gnrs automatiquement par Xcode et leur
valeur importe peu pour l'instant. Nous y reviendrons un peu plus loin dans
ce livre.

Enn, la ligne 7 matrialise la n du chier ViewController.h :


1

@end

Contrle-glissez-dposez le bouton de la zone d'dition dans le volet de code, juste


au-dessus de la dernire ligne, comme la gure 2.15.

Figure 2.15  Un contrle-glisser-dposer au-dessus de la dernire ligne de code

24

CRITURE DU CODE

Au relchement du bouton de la souris, une bote de dialogue est ache. Ici, nous
voulons associer une action au bouton, an qu'un message soit ach dans le Label
lorsque l'utilisateur appuie sur le bouton. Choisissez Action dans la liste droulante
Connection et tapez  reagir  dans la zone de texte Name. La bote de dialogue devrait
maintenant ressembler la gure 2.16.

Figure 2.16  La bote de dialogue permet d'associer une action au bouton

Comme vous pouvez le voir sur cette image, l'action reagir (paramtre Name), excute
lorsque l'utilisateur appuie sur le bouton (Touch Up Inside, soit  au relchement du
bouton de la souris  dans le paramtre Event), est sur le point d'tre dnie.
Cliquez sur Connect. Le code est complt avec une nouvelle instruction :
1
2
3
4
5
6
7
8
9

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
@property ( weak , nonatomic ) IBOutlet UILabel * message ;
- ( IBAction ) reagir :( id ) sender ;
@end

Comme vous pouvez le voir, une ligne a t ajoute dans le code pour dclarer l'action
reagir dans le code (ligne 7).

criture du code
Cliquez sur l'entre ViewController.m dans le volet de navigation. Un code assez
imposant apparat dans la partie centrale de la fentre. Il a (gentiment) t gnr par
Xcode.
1
2
3
4
5
6

//
//
//
//
//
//

ViewController . m
premier
Created by Michel Martin on 24 / 10 / 11 .
Copyright (c ) 2011 __MyCompanyName__ . All rights reserved .

25

CHAPITRE 2.

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

26

UN PREMIER DVELOPPEMENT

//
# import " ViewController . h "
@implementation ViewController
@synthesize message ;
- ( void ) didReceiveMemoryWarning
{
[ super didReceiveMemoryWarning ];
// Release any cached data , images , etc that aren 't in use .
}
# pragma mark - View lifecycle
- ( void ) viewDidLoad
{
[ super viewDidLoad ];
// Do any additional setup after loading the view , typically
from a nib .
}
- ( void ) viewDidUnload
{
[ self setMessage : 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 ];
}

CONSTRUCTION ET EXCUTION

56
57
58
59
60
61
62
63
64

- ( BOOL ) shouldAutorotateToInterfaceOrientation :(
UIInterfaceOrientation ) interfaceOrientation
{
// Return YES for supported orientations
return ( interfaceOrientation !=
UIInterfaceOrientationPortraitUpsideDown ) ;
}
- ( IBAction ) reagir :( id ) sender {
}
@end

Vous avez sans doute remarqu que certaines lignes de code ne sont pas
alignes gauche ; c'est ce qu'on appelle indenter son code. Le but est
d'amliorer la lisibilit du code en dnissant visuellement sa structure. Vous
pouvez utiliser des tabulations ou des espaces, selon votre prfrence.

Jetez un il aux dernires lignes du code. Est-ce que cela ne vous rappelle rien ? La
ligne 62 est la copie conforme de la dclaration qui a t gnre lorsque vous avez
contrle-gliss-dpos le bouton de la zone d'dition dans le chier ViewController.h.
Avez-vous remarqu les accolades, juste aprs le mot sender ? C'est cet endroit que
vous allez crire le code qui permettra d'acher un message dans le Label lorsque
l'utilisateur clique sur le bouton. Compltez cette dclaration comme suit :
1
2
3
4

- ( IBAction ) reagir :( id ) sender {


NSString * lemessage = [[ NSString alloc ] initWithFormat : @ "
Bravo ! " ];
message . text = lemessage ;
}

Copier ce code
Code web : 444818

Mais qu'est-ce que tout ce charabia ? C'est comme a que parle mon iPhone ?

Ce n'est pas comme a que parle votre iPhone, mais plutt comme a qu'Objective-C
se fait comprendre de votre device. Je sais que la syntaxe de ces instructions a de quoi
surprendre. Ne vous en faites pas, et surtout, n'essayez pas de tout comprendre tout
de suite. Pour l'instant, contentez-vous de voir le mot  Bravo  sur la deuxime ligne.
C'est ce mot qui sera ach sur l'iPhone lorsque vous cliquerez sur le bouton.

Construction et excution
Dans la barre d'outils, cliquez sur l'icne Run (gure 2.17).
27

CHAPITRE 2.

UN PREMIER DVELOPPEMENT

Figure 2.17  L'icne Run de la barre d'outils

Au bout de quelques instants, une fentre complmentaire nomme Simulateur iOS


est ache, et l'application apparat dans son tat initial. Cliquez sur le bouton. Le
texte  Bravo !  remplace le texte  Cliquez sur le bouton , comme la gure 2.18.
Je vous flicite ! Vous venez de raliser votre premire application sur iPhone !

Figure 2.18  Votre premire application iPhone !

En rsum
 Le design des applications est dni dans la composante Interface Builder de l'application Xcode.
28

CONSTRUCTION ET EXCUTION

 La bibliothque d'objets est accessible en cliquant sur l'icne Hide or Show the
Utilities, puis sur l'icne Show the Object library.
 Pour ajouter un contrle dans une vue, il sut de le glisser-dposer depuis la bibliothque d'objets dans le Storyboard.
 Pour relier un contrle au code, contrle-glissez-dposez-le depuis le Storyboard
dans le chier .h correspondant et indiquez si vous voulez crer un outlet ou une
action.
 Le code de l'application est crit dans le chier .m qui correspond la vue.
 Pour construire et excuter l'application dans le simulateur iOS, il sut de cliquer
sur l'icne Run, dans l'angle suprieur gauche de la fentre de Xcode.

29

CHAPITRE 2.

30

UN PREMIER DVELOPPEMENT

Chapitre

Le simulateur iOS
Dicult :

e simulateur iOS fait partie intgrante de Xcode. Cette application permet de simuler
le fonctionnement d'un iPhone, d'un iPod Touch et d'un iPad. Que vous ayez rejoint la
communaut des dveloppeurs Apple ou non, vous utiliserez frquemment le simulateur
pour tester rapidement vos applications. Il est donc important de savoir l'utiliser.
Dans le chapitre prcdent, vous avez eu un premier contact avec le simulateur iOS. Dans
ce chapitre, vous allez faire plus ample connaissance avec lui. Vous apprendrez entre autres
simuler les gestuelles de l'utilisateur, installer et dsinstaller une application et bien
d'autres choses encore.

31

CHAPITRE 3.

LE SIMULATEUR IOS

Les bases
Lorsque vous dnissez un nouveau projet Xcode, vous devez choisir un type de device :
iPhone/iPod Touch ou iPad (gure 3.1).

Figure 3.1  Xcode vous demande de choisir un type de device

Si vous voulez utiliser le simulateur iOS, vous pouvez tout moment changer de device
en utilisant la liste droulante Scheme, dans la partie suprieure gauche de la fentre
de Xcode (gure 3.2).

Figure 3.2  Vous pouvez tout moment changer le device du simulateur partir de

Xcode

Une autre possibilit consiste utiliser le menu du simulateur. La fentre de ce dernier


tant en avant-plan, droulez le menu Matriel, pointez Appareil et choisissez un des
devices proposs, comme la gure 3.3.
32

SIMULER LES GESTUELLES ET LES ACTIONS DE L'UTILISATEUR

Figure 3.3  Le device peut galement tre choisi directement via le simulateur

Le menu Matriel ore des possibilits complmentaires, puisqu'il est possible de


simuler la version du systme iOS (on dit aussi rmware ) utilis. Droulez le menu
Matriel, pointez Version et choisissez la version d'iOS utiliser, comme la gure
3.4.

Figure 3.4  Il est galement possible de choisir la version d'iOS


Cette commande est trs pratique pour s'assurer qu'une application fonctionne bien sur toutes les versions du rmware.

Une fois le simulateur iOS choisi comme cible de l'application, cliquez sur le bouton
Run pour lancer l'application dans le simulateur.

Simuler les gestuelles et les actions de l'utilisateur


Le simulateur iOS est une application Mac. Il s'excute dans une fentre ache sur
l'cran reli votre ordinateur. tant donn que cet cran est une simple dalle rserve
l'achage, il n'est pas capable de ragir aux gestuelles ni aux actions eectues sur
33

CHAPITRE 3.

LE SIMULATEUR IOS

un iPhone/iPod Touch/iPad. Toutefois les ingnieurs en charge du dveloppement de


cette application ont eu la bonne ide de lui associer des raccourcis clavier pour simuler
les gestuelles et les actions des utilisateurs.

Simuler les gestuelles de l'utilisateur


Vous vous en doutez, il n'est pas possible de faire tourner votre cran d'ordinateur ou
de le secouer pour simuler ces actions dans le simulateur iOS. Par contre, vous pouvez
utiliser des commandes dans le menu Matriel du simulateur iOS, ou les raccourcis
clavier quivalents.
Action

Commande dans Raccourci


le menu Matriel

Rotation d'un quart de Rotation gauche


tour gauche
Rotation d'un quart de Rotation droite
tour droite
Verrouillage
Verrouiller
Secousse
Secousse
cran d'accueil
cran d'accueil

Commande + Gauche
Commande + Droite
Commande + L
Ctrl + Commande + Z
Maj + Commande + H

Simuler les actions de l'utilisateur


Les actions lies au toucher (clic, double-clic, agrandir, etc.) peuvent galement tre
simules dans le simulateur iOS en utilisant la souris.
Action sur le device

Toucher
Toucher et maintenir
Feuilleter

Action dans le simulateur

Cliquez.
Maintenez le bouton gauche enfonc.
Placez le pointeur sur l'objet dplacer, maintenez le
bouton gauche enfonc, dplacez l'objet puis relcher le
bouton gauche.
Glisser-dposer
Placez le pointeur sur l'objet dplacer, maintenez le
bouton gauche enfonc, dplacez l'objet puis relchez le
bouton gauche.
Zoom avant, zoom arrire Maintenez la touche Option enfonce. Deux ronds semiopaques apparaissent sur l'cran. Maintenez le bouton
gauche de la souris enfonc et dplacez la souris dans la
direction souhaite pour obtenir le redimensionnement.
34

QUELQUES PRATIQUES CONNATRE

Quelques pratiques connatre


Installer/dsinstaller une application
Pour installer une application, il sut de l'excuter dans le simulateur en cliquant sur
le bouton Run de Xcode. Elle est alors disponible sur l'cran des applications (gure
3.5), et le restera jusqu' ce que vous la dsinstalliez.

Figure 3.5  Il est possible d'installer des applications dans le simulateur

Pour dsinstaller une application, pointez son icne et maintenez le bouton gauche de
la souris enfonc jusqu' ce que toutes les icnes se mettent bouger. Cliquez alors sur
la case de fermeture de l'application que vous voulez dsinstaller (gure 3.6).
Si vous n'avez plus l'intention de dsinstaller une application, il vous sut
de cliquer sur le bouton principal, en bas du simulateur pour arrter la danse
des icnes.

Retourner la conguration d'usine


Une commande permet de rinitialiser le simulateur iOS pour lui redonner sa conguration d'usine, c'est--dire sa conguration juste aprs l'installation de Xcode. Toutes les
applications installes, contenus et rglages sont supprims et placs dans la corbeille
du Mac. Pour rinitialiser votre simulateur iOS, cliquez sur le menu Simulateur iOS
35

CHAPITRE 3.

LE SIMULATEUR IOS

Figure 3.6  La croix permet de dsinstaller une application du simulateur

et slectionnez Rinitialiser le contenu et les rglages. Une bote de dialogue


de conrmation est ache. Cliquez sur Rinitialiser pour conrmer votre choix.

Dboguer une application lors de son excution sur le simulateur


L'application Xcode est dote d'un volet de dbogage, aussi appel  console . Ce volet
permet d'acher des informations textuelles pendant qu'une application s'excute,
et ce, quelle qu'en soit la cible : le simulateur iOS ou un device rel. Cette section
est une premire approche du dbogage. N'ayant pas encore abord l'excution d'une
application sur un device, vous allez apprendre acher des donnes dans la console
pendant l'excution sur le simulateur iOS.
Pour acher le volet de dbogage, il sut de cliquer sur l'icne Hide or show the
Debug area, dans la barre d'outils de Xcode (gure 3.7).
Vous utiliserez une instruction, NSLog(), pour acher des informations dans le volet
de dbogage :
1

NSLog ( @ " Le texte afficher ") ;

Comme vous pouvez le voir sur la gure 3.7, l'instruction


 Bonjour  dans le volet de dbogage ( la dernire ligne).
36

NSLog()

ache le texte

QUELQUES PRATIQUES CONNATRE

Figure 3.7  Le bouton Hide


dbogage

or show the Debug area permet d'acher le volet de

En rsum
 Le simulateur iOS fait partie intgrante de l'application Xcode.
 La liste Scheme (dans l'angle suprieur gauche de la fentre de Xcode) permet de
choisir si l'application s'excutera dans le simulateur iPhone ou dans le simulateur
iPad. Vous pouvez galement utiliser la commande Appareil dans le menu Matriel
pour parvenir au mme rsultat. Si vous le dsirez, vous pouvez galement choisir la
version d'iOS utilise avec la commande Version dans le menu Matriel.
 Certaines gestuelles et actions de l'utilisateur peuvent tre reproduites dans le simulateur iOS, l'aide de commandes dans le menu Matriel ou de raccourcis clavier.
 Une application peut acher des informations textuelles dans le volet de dbogage
en utilisant l'instruction NSLog().

37

CHAPITRE 3.

38

LE SIMULATEUR IOS

Deuxime partie
Le langage Objective-C

39

Chapitre

Les bases de l'Objective-C


Dicult :

omme je vous le disais dans la premire partie de ce livre, nous allons utiliser le langage
Objective-C pour dvelopper nos applications. Et pour bien comprendre comment
fonctionne l'Objective-C, vous devez dans un premier temps en acqurir les bases. Tout
ce qui sera dit ici vous sera protable lorsque vous crirez des applications en Objective-C.
Nous allons y aller en douceur et vous verrez que, progressivement, vous serez capables de
raliser de plus en plus de choses avec ce langage. Alors allons-y !

41

CHAPITRE 4.

LES BASES DE L'OBJECTIVE-C

Avant tout chose, je vous rappelle que le langage Objective-C hrite du langage C,
c'est--dire que leur syntaxe de base est relativement similaire. Si vous connaissez dj
le C, vous pouvez directement vous rendre au chapitre suivant. Si vous voulez en savoir
plus sur le langage C, le Site du Zro propose un tutoriel.


Lire le tutoriel  Apprenez
B programmer en C 
Code web : 309047


Tout ce qui va tre dit dans ce chapitre est relativement thorique. Malheureusement,
c'est un passage oblig pour apprendre le langage Objective-C. Cependant, rien ne vous
empche de tester ce que vous apprenez au fur et mesure.
Pour commencer, dnissez un nouveau projet appel  test  bas sur le modle Single
View Application. Cliquez sur ViewController.m dans le volet de navigation (1) et
entrez les instructions tester dans la mthode viewDidLoad, juste aprs le message
[super viewDidLoad]; (2), comme indiqu la gure 4.1.

Figure 4.1  Insrez une instruction dans votre code

Pour tester votre code, une des faons les plus simples consiste acher des lments
textuels dans le volet de dbogage (aussi appel  console ) avec la fonction NSLog().
titre d'exemple, tapez cette ligne de code la suite de [super viewDidLoad] :
1

NSLog ( @ " texte afficher " ) ;

Cliquez sur l'icne Run (1) pour excuter l'application et, si ncessaire, cliquez sur
Hide or show the Debug area (2) pour acher le volet de dbogage. Comme vous
pouvez le constater la gure 4.2, le texte pass la fonction NSLog() est ach dans
le volet de dbogage.
42

INSTRUCTIONS

Figure 4.2  Le texte est bien ach


Est-ce que NSLog() peut acher autre chose que du texte ?

Oui, bien sr. N'ayez crainte, vous dcouvrirez cela en temps utile. Passez vite la
suite pour faire connaissance avec vos premires instructions Objective-C.

Instructions
Avant de pouvoir conduire une voiture, vous devez apprendre un certain nombre de
rgles. Pour cela, vous devez potasser le code de la route. Une fois cette premire tape
acquise, vous pouvez vous lancer dans la conduite. L encore, vous devez apprendre
plusieurs choses. Certaines ne sont pas essentielles. Par exemple, il n'est pas indispensable de savoir comment fonctionne le moteur de la voiture. D'autres sont par contre
vitales : il est impensable de se mettre au volant d'une voiture si on ne sait pas mettre
en route le moteur ou passer les vitesses !
Les choses sont assez similaires en programmation. Vous allez devoir apprendre des
rgles, acqurir des mcanismes et beaucoup pratiquer avant d'arriver faire ce que
vous voulez. Cela vous prendra du temps et de l'nergie, mais imaginez quelle joie vous
prouverez lorsqu'une de vos applications sera tlcharge, utilise et apprcie par des
milliers d'inconnus ! Pour l'instant, nous n'en sommes pas l. Commenons dj par les
bases de la programmation.
Tous les programmes sont constitus d'instructions. Une instruction demande l'ordi43

CHAPITRE 4.

LES BASES DE L'OBJECTIVE-C

nateur d'eectuer quelque chose de prcis. Gnralement, on crit une seule instruction
par ligne.
Voici une instruction Objective-C plutt simple :
1

int leNombreDix = 10 ;

Et voici une instruction Objective-C un peu plus complique :


1

NSDateFormatter * miseEnForme = [[ NSDateFormatter alloc ] init ];

Je suis sr que vous trouvez la premire plus sympathique que la deuxime. Mais
rassurez-vous, ces deux instructions sont trs simples comprendre du moment que
l'on connat le  code de la route  Objective-C.
Pour l'instant, contentez-vous de retenir qu'un programme est constitu d'un ensemble d'instructions. Au l des chapitres, votre comprhension du langage ObjectiveC sera de plus en plus claire et vous pourrez commencer concevoir vos propres applications.
Je vois que toutes les lignes se terminent par un  ; . Est-ce que ce caractre
est obligatoire ?

Eh bien oui, le  ;  est obligatoire. Il indique l'ordinateur que l'instruction est termine. Il faudra donc vous y faire : toutes les instructions se terminent par un  ; .

Variables, constantes et oprateurs


Les variables
Le langage Objective-C n'aurait aucun intrt s'il n'tait pas capable de manipuler des
donnes. Ceci est possible grce aux variables. En eet, ces dernires permettent de
stocker temporairement des informations dans la mmoire de votre device et d'y accder
par la suite. Grce elles, vous allez pouvoir stocker l'ge ou la taille du visiteur, mais
aussi eectuer des calculs et bien d'autres choses encore.
Le terme  variable  a t choisi car la donne mmorise est susceptible
de changer de valeur pendant l'excution du programme. Elle est donc. . .
variable.

Pour dnir une variable, vous utiliserez la syntaxe suivante :


1

type nomVariable ;

O :
 type est le type de la variable. Cet lment indique ce que la variable est cense
reprsenter : un entier, un nombre virgule, un caractre, etc.
44

VARIABLES, CONSTANTES ET OPRATEURS

nomVariable

est le nom de la variable.

Souvenez-vous qu'une instruction doit se terminer par un  ; .

Par exemple, pour dnir une variable nomme  maVariable  dont le type est int,
vous utiliserez l'instruction suivante :
1

int maVariable ;

Pas si vite ! Qu'est-ce que veut dire int et pourquoi le deuxime mot est
orthographi ainsi : maVariable et pas Ma variable ?

vient du mot anglais integer ( entier  en franais). Il faudra vous y faire : la


plupart des langages de programmation sont en anglais. Pour ceux qui auraient des
lacunes en maths, un entier est un nombre sans virgule, comme par exemple 12 ou
65241.
Quant la syntaxe du deuxime mot, elle adopte la convention camelCase, qui consiste
utiliser une premire lettre minuscule et une lettre majuscule pour chaque nouveau
mot. Cette faon de faire n'est pas obligatoire, c'est juste une convention : vos programmes fonctionneront quand mme si vous ne l'utilisez pas.
De plus, l'Objective-C interdit les espaces et les accents dans les noms de variables.
Par exemple, maPremiereVariable respecte la convention camelCase et ne contient
ni espace ni accent ; le nom est donc correct. A contrario, Ma premire variable ne
respecte pas la convention camelCase et contient des espaces et un accent ; le nom est
donc incorrect.
int

Notez galement qu'Objective-C est sensible la casse des caractres, c'est-dire aux minuscules et aux majuscules. Ainsi par exemple, les variables
unEntier, UnEntier et UNentier sont direntes. Si vous tentez d'utiliser plusieurs de ces noms pour dsigner une mme variable, des erreurs se
produiront et l'application ne pourra pas s'excuter.

Si vous le souhaitez, il est possible d'aecter une valeur une variable pendant sa
dclaration. Vous utiliserez alors la syntaxe suivante :
1

type nomVariable = valeur ;

O type est le type de la variable, nomVariable est son nom et valeur est la valeur
que vous voulez lui aecter. Par exemple :
1

int maVariable = 10 ;

Ici, la valeur 10 est aecte la variable maVariable de type int.


Vous pouvez manipuler ces variables comme bon vous semble. Par exemple :
45

CHAPITRE 4.

1
2

LES BASES DE L'OBJECTIVE-C

int resultat , nombre1 = 10 , nombre2 = 5 ;


resultat = nombre1 + nombre2 ;

Ici la variable resultat vaudra 15 : 10 + 5 = 15. Bon, je vous l'accorde, pour le


moment a ne nous sert pas grand-chose. Mais croyez-moi, c'est primordial.
Notez que pour la premire instruction, je n'ai renseign qu'une seule fois le
type des variables, avant de les sparer par des virgules. C'est plus rapide
crire (oui les dveloppeurs sont des fainants).

Que diriez-vous maintenant d'un peu de pratique ? Ouvrez votre projet de test, celui
dni quelques pages avant.
Comme vous le montre la gure 4.3, cliquez sur ViewController.m (1) dans le volet
de navigation, reprez la mthode viewDidLoad et ajoutez les deux lignes de code
prcdentes la suite de [super viewDidLoad].
Ajoutez un NSLog pour acher la valeur de la variable resultat dans le volet de
dbogage :
1

NSLog ( @ " R sultat vaut % d " , resultat ) ;

Cliquez sur Run (2) pour excuter l'application. Si le volet de dbogage n'est pas ach,
cliquez sur Hide or show the Debug area (3). Au bout de quelques instants, le volet
de dbogage ache rement le rsultat.

Figure 4.3  Le rsultat est ach dans le volet de dbogage

46

VARIABLES, CONSTANTES ET OPRATEURS

Avez-vous remarqu l'trange  %d  dans la fonction NSLog() ? Ce paramtre indique Xcode le type de la valeur acher. Ici, %d signie  variable
entire .

Le langage Objective-C peut utiliser plusieurs autres types de variables. Les plus frquents ont t rassembls dans le tableau ci-dessous. Ne vous attardez pas trop sur
ce tableau. Vous y reviendrez dans les sections suivantes, lorsque vous testerez des
variables d'un de ces types.
Type

%@
%d, %i
%f
%c

Signication

Objet Cocoa. NSString par exemple


Entier sign (c'est--dire avec un signe  -  si ncessaire)
Float ou Double
Caractre

Les constantes
Les constantes sont comparables aux variables, ceci prs qu'une fois dnies leur
valeur ne peut pas changer. Voici la syntaxe utiliser :
1

const type nomConstante = valeur ;

La syntaxe est identique celle des variables, ceci prs que l'on ajoute le mot-cl
const au dbut de l'instruction.
Par exemple :
1

const float pi = 3 . 1415926536 ;

En rsum, vous utiliserez des variables pour mmoriser des valeurs qui peuvent changer dans le temps et des constantes pour stocker des valeurs xes tout au long du
programme (une TVA de 19,6 % par exemple).

Les oprateurs
Comme leur nom le laisse supposer, les oprateurs permettent d'eectuer des oprations. Dans cette section, nous allons nous intresser aux oprateurs d'aectation et
aux oprateurs arithmtiques.
Oprateurs d'aectation

Les oprateurs utilisables en Objective-C sont regroups dans le tableau qui suit.
Il existe d'autres oprateurs d'aectation, mais nous les passerons sous silence
pour l'instant car ils risqueraient de vous embrouiller. Arrivs ce point du
livre, ce qui compte c'est que vous compreniez la logique d'utilisation des
oprateurs d'aectation.

47

CHAPITRE 4.

LES BASES DE L'OBJECTIVE-C

Oprateur

Signication

-=

Soustraction de la valeur spcie


Divise par la valeur spcie

=
+=

/=

Aectation
Ajout de la valeur spcie

Exemple

int maVariable = 2;
maVariable += 5;
Ajoute 5 maVariable.
maVariable -= 5;
Soustrait 5 maVariable.
maVariable /= 5;
Divise par 5 maVariable.
maVariable *= 5;
Multiplie par 5 maVariable.
maVariable %= 5;
Stocke dans maVariable

Multiplie par la valeur spcie


Donne le reste de la division
entire dont le diviseur est
le
spci
reste de la division entire de
maVariable par 5.

*=
%=

Je ne comprends rien ce tableau ! Quelques explications seraient les bienvenues.

L'instruction suivante (issue de la deuxime ligne du tableau) vous parat certainement


un peu farfelue, voire mme totalement incomprhensible :
1

maVariable += 5 ;

Il s'agit d'une facilit, ou plutt d'un raccourci d'criture. Cette instruction est quivalente :
1

maVariable = maVariable + 5 ;

Est-ce que c'est plus clair pour vous maintenant ? Ou avez-vous encore un peu de mal
comprendre comment on peut stocker dans maVariable la valeur maVariable + 5 ?
Si vous accrochez l-dessus, sachez que le rsultat de maVariable + 5 est calcul dans
un premier temps, puis ensuite stock dans maVariable.
Les autres oprateurs d'aectation fonctionnent de mme. Ainsi par exemple :
1

maVariable %= 5 ;

Est quivalent :
1

maVariable = maVariable % 5 ;

Aprs l'excution de cette instruction, maVariable contient le reste de la division entire (%) de maVariable par 5 (maVariable % 5).
C'est quoi exactement ce % dont tu nous parles ?

48

VARIABLES, CONSTANTES ET OPRATEURS

C'est ce qu'on appelle un modulo. Il permet d'obtenir le reste d'une division. Par
exemple, si je divise 5 par 2 (5/2), il reste 1. Ainsi, 5%2 = 1
Oprateurs arithmtiques

Vous connaissez forcment les quatre oprateurs arithmtiques de base : plus, moins,
divis par et multipli par. Vous aurez galement faire quelques autres oprateurs,
moins frquents mais trs utiles en programmation. Je les ai regroups dans le tableau
suivant.
Oprateur Fonction
+
++
-*
/
%

Addition
Soustraction ou inversion de signe
Incrmentation (ajout de 1)
Dcrmentation (soustraction de 1)
Multiplication
Division
Modulo (reste de la division entire)

Ne soyez pas erays si c'est la premire fois que vous rencontrez certains de ces oprateurs.
 ++ ajoute 1 une variable entire. titre d'exemple, variable++ ou ++variable
est quivalent variable = variable + 1.
 -- soustrait 1 d'une variable entire. titre d'exemple, variable-- ou --variable
est quivalent variable = variable - 1.
 % renvoie le reste d'une division entire. Par exemple 15%2 renvoie 1. En eet, si
vous divisez 15 par 2, le reste de la division est 1.
Et maintenant, voici quelques exemples d'utilisation :
1
2
3
4
5
6

int var1 = 10 ;
int var2 = 15 ;
int result ;
result = var1 * var2 ;
result ++;
result = 15 % 10

 Les lignes 1 et 2 dnissent les variables int var1 et var2 valant (respectivement)
10 et 15.
 La ligne 3 dnit la variable int result, mais ne lui aecte aucune valeur.
 La ligne 4 aecte result le rsultat de la multiplication de var1 par var2. Aprs
l'excution de cette instruction, result vaut donc 150 (10 15).
 La ligne 5 ajoute 1 la variable result. Cette dernire vaut donc 151 aprs l'excution de l'instruction.
 Enn, la ligne 6 aecte result le reste de la division entire de 15 par 10. Aprs
l'excution de cette instruction, result vaut 5. En eet 15/10 = 1, reste 5.
49

CHAPITRE 4.

LES BASES DE L'OBJECTIVE-C

Lorsque plusieurs oprateurs apparaissent dans une expression mathmatique, il est


ncessaire de savoir dans quel ordre ils sont utiliss. Pour les oprateurs +, -, * et
/, les rgles sont les mmes que dans l'algbre traditionnelle. savoir que * et / sont
prioritaires par rapport + et -. En cas de priorits identiques, les calculs sont eectus
de gauche droite.
D'aprs vous, quelle est la valeur stocke dans la variable result ?
1

float result = 10 * 2 + 120 / 2 ;

Le rsultat de cette opration est 80. L'valuation se fait en calculant 10 2 puis 120/2.
Ces deux valeurs sont ensuite ajoutes. Ainsi 20 + 60 = 80.
Si ncessaire, vous pouvez utiliser un ou plusieurs jeux de parenthses pour modier
l'ordre d'valuation, et donc le rsultat. D'aprs vous, quelle est la valeur stocke dans
la variable result ?
1

float result = 10 * ( 2 + 120 ) / 2 ;

Le rsultat est 610. L'opration 2+120 tant entoure de parenthses, elle est prioritaire
et donc calcule en premier. Les oprateurs * et / ayant le mme niveau de priorit,
l'expression est value de la gauche vers la droite. Ainsi, result a pour valeur 10
multipli par 122 puis divis par 2, soit 610.
L'oprateur unaire - (en d'autres termes, le  -  qui inverse le signe d'un nombre
ou d'une variable) est prioritaire. Il en va de mme des oprateurs ++ et -- lorsqu'ils
sont utiliss en prxe (++variable et --variable). Ils sont donc excuts en premier.
Viennent ensuite au mme niveau les oprateurs *, / et %, et enn les oprateurs + et -.
Et maintenant, un peu de pratique !
Dans votre projet de test, cliquez sur ViewController.m dans le volet de navigation,
reprez la mthode viewDidLoad et ajoutez les lignes de code prcdentes la suite
de [super viewDidLoad]. Invoquez la fonction NSLog() chaque fois que vous voulez
tester une variable. Voici quoi pourrait ressembler la mthode viewDidLoad :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

50

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
int var1 = 10 ;
int var2 = 15 ;
int result ;
result = var1 * var2 ;
NSLog ( @ " var1 * var2 = % d " , result ) ;
result ++;
NSLog ( @ " Apr s le ++ , result vaut
result = 15 % 10 ;
NSLog ( @ " 15 %% 10 vaut

% d " , result ) ;

% d " , result ) ;

float result1 = 10 * 2 + 120 / 2 ;

VARIABLES, CONSTANTES ET OPRATEURS

18
19
20
21
22

NSLog ( @ " 10 * 2 + 120 / 2 vaut

% f " , result1 ) ;

float result2 = 10 * (2 + 120 ) / 2;


NSLog ( @ " 10 * ( 2 + 120 ) / 2 vaut % f " , result2 ) ;

Copier ce code
B
Code web : 494253


Cliquez sur Run pour excuter l'application. Si le volet de dbogage n'est pas ach,
cliquez sur Hide or show the Debug area. Au bout de quelques instants, le volet de
dbogage ache les divers rsultats. Comme vous pouvez le voir la gure 4.4, ils sont
conformes aux attentes.

Figure 4.4  Les rsultats sont bien achs et sont corrects

Avant d'en terminer avec ceci, je voudrais faire une remarque sur une des fonctions
NSLog() utilises dans ce code.
Avez-vous remarqu un dtail surprenant dans l'instruction suivante, vers le milieu de
la mthode viewDidLoad ?
1

NSLog ( @ " 15 %% 10 vaut

% d " , result ) ;

Le signe  %  a une signication particulire. En eet, associ une lettre (%d ou


%f par exemple), il prcise le type d'une variable que l'on dsire acher. Dans cette
instruction, on dsire acher le signe  %  dans le volet de dbogage. C'est la raison
pour laquelle il est doubl.
51

CHAPITRE 4.

LES BASES DE L'OBJECTIVE-C

Commentaires
Un commentaire est un texte dans un programme, non pris en compte lors de l'excution de ce dernier. Ils sont trs utiles en programmation puisqu'ils vous permettent
de vous y retrouver dans votre code. Imaginez que vous criez une application et que,
quelques mois ou mme quelques annes plus tard, vous dcidiez de la mettre jour.
Mme si vous tes l'auteur du code, il vous sera dicile de tout comprendre au premier
coup d'il. C'est pourquoi il est fortement recommand d'insrer des commentaires qui
expliquent de manire claire ce que vous avez fait.
Pour insrer un commentaire qui tient sur une seule ligne, vous le ferez prcder d'un
double slash :
1

int maVariable = 10 ; // maVariable vaut 10

Ce qui se trouve avant le double slash n'est pas un commentaire. Vous notez
d'ailleurs que le  ;  se trouve avant le commentaire ; ce dernier ne fait donc
pas partie de l'instruction.

Si le commentaire s'tale sur plusieurs lignes, vous utiliserez les caractres  /*  pour
marquer le dbut et  */  pour marquer la n du commentaire :
1
2
3
4
5

/*
Ceci est un commentaire
sur
plusieurs lignes
*/

Types de donnes
Les variables utilises jusqu'ici taient de type entier (int) et virgule (float). Ces
deux types ne sont pas les seuls. Vous allez maintenant dcouvrir les dirents types
de base utilisables en Objective-C. Vous apprendrez galement eectuer des conversions entre ces dirents types de donnes.
Les types plus complexes seront abords progressivement dans les chapitres
suivants.

Boolens
Le type BOOL est utilis lorsque vous devez manipuler des informations de type vrai/faux,
oui/non ou 0/1. Ces informations sont dites  boolennes .
Voici quelques exemples de dclaration :
52

TYPES DE DONNES

1
2
3
4

BOOL
BOOL
BOOL
BOOL

booleen1
booleen2
booleen3
booleen4

NO

=
=
=
=

0;
NO ;
1;
YES ;

et 0 sont quivalents ; YES et 1 le sont galement.

Entiers
Il n'existe pas un mais plusieurs types de variables entires. Vous choisirez un type
plutt qu'un autre en fonction des valeurs maximales que peuvent prendre les variables
ou constantes concernes.
Variable

short int
unsigned short int
unsigned int et unsigned long int
int et long int
long long int
unsigned long long int

Valeurs possibles

-32768 32768
0 65535
0 4294967295
-2147483647 2147483647
-9223372036854775807 9223372036854775808
0 18446744073709551615

Par exemple :
1
2

int variableEntiere = 123456 ;


short int entierCourt = - 54 ;

Rels
Les rels, aussi appels  nombres virgule ottante , sont des nombres virgule,
comme par exemple 176.45 ou encore -0.561. Selon leur prcision (c'est--dire selon
le nombre de chires aprs la virgule), ils sont mmoriss dans des variables de type
float ou double.
Comme pour la plupart des langages de programmation, les nombres virgule
s'crivent avec un point ( . ) et non une virgule ( , ) : 4.5 et non 4,5.

Les variables/constantes de type float peuvent tre comprises entre 3.4 1038 et
3.41038 . Quant aux variables/constantes de type double, elles peuvent tre comprises
entre 1.7 10308 et 1.7 10308 .
53

CHAPITRE 4.

LES BASES DE L'OBJECTIVE-C

Que signie 3.4 1038 ?

Il s'agit d'une convention d'criture dite  scientique . 1038 signie 38 zros avant
la valeur numrique. Et 3.4 signie que le nombre 3.4 est multipli par le nombre
1038 . Si vous avez du mal visualiser tout a, la gure 4.5 devrait vous aider.

Figure 4.5  3.4 1038 est en fait un nombre virgule avec 38 zros

Caractres
Le type char permet de manipuler des chanes composes d'un et d'un seul caractre.
Le caractre manipul doit tre dlimit par des apostrophes :
1

char monCaractere = 'a ';

Les pointeurs
Les pointeurs sont gnralement redouts comme la peste par les programmeurs dbutants. Pourtant, ils rendent de grands services et vous devez absolument comprendre
leur fonctionnement pour bien programmer en Objective-C. Pour l'instant, retenez leur
principal intrt : ils facilitent la manipulation des objets en Objective-C. Jusqu'ici,
tout va bien. Nous allons donc aller un peu plus loin.
Sachez que les pointeurs ne sont pas un type de donnes. Il est donc impossible
d'crire quelque chose comme ceci :
1

pointer maVariable ;

Contrairement aux types de donnes, les pointeurs ne sont pas utiliss pour stocker
des donnes, mais des adresses. Par exemple, lorsque vous faites int monEntier =
10; , un espace en mmoire (dont la taille dpend du type de la variable) est rserv
pour stocker la valeur 10. Cet espace se trouve l'adresse &monEntier. Utilisons une
instruction NSLog pour acher la valeur et l'adresse de la variable monEntier :
1

54

NSLog ( @ " monEntier vaut % i et son adresse en m moire est % p" ,


monEntier , & monEntier ) ;

LES POINTEURS

Voici le rsultat ach dans la console :


[...] monEntier vaut 10 et son adresse en m moire est 0 xbfffd6f4

Remarquez l'utilisation de la chane %p pour acher le pointeur. Chaque fois


que vous voudrez acher l'adresse contenue dans un pointeur, vous utiliserez
une chane %p.

Ce qui vient d'tre dit n'est peut-tre pas trs clair pour vous. Si tel est le cas, nous
allons prendre quelques instants pour approfondir les choses. Sans vouloir jeter un
froid, voici une dnition sur laquelle vous devriez mditer :  un pointeur est une
variable qui contient l'adresse d'une autre variable d'un type donn .
Examinez la gure 4.6.

Figure 4.6  L'emplacement d'adresse 17 contient un pointeur vers l'emplacement

d'adresse 207

Le rectangle horizontal reprsente une partie de la mmoire de votre ordinateur. Chaque


case correspond un emplacement en mmoire. Pour reprer facilement les dirents
emplacements, on leur aecte un nombre appel  adresse . Dans cette gure, l'emplacement d'adresse 17 contient un pointeur vers l'emplacement d'adresse 207. En utilisant
le  pointeur  d'adresse 17, on pourra donc accder la donne stocke l'adresse
207. En rsum :
 les pointeurs sont utiliss pour mmoriser des adresses, pas des donnes ;
 les donnes contenues dans les emplacements en mmoire ainsi  points  peuvent
changer ;
 les variables, quant elles, ont un type dni une fois pour toutes et sont donc
 ges .
Les deux derniers points reprsentent la dirence essentielle entre les pointeurs et
les variables. Si vous rchissez cela, vous dcouvrirez un autre intrt majeur des
pointeurs : ils font rfrence des donnes dont le contenu et la taille peuvent changer.
55

CHAPITRE 4.

LES BASES DE L'OBJECTIVE-C

Si vous ne comprenez pas encore trs bien le pourquoi du comment, ne vous


attardez pas trop sur ce qui vient d'tre dit. C'est en utilisant les pointeurs
que vous comprendrez leur intrt et, trs vite, vous ne pourrez plus vous en
passer !

Voyons comment dnir un pointeur en Objective-C :


1

int * pointeurSurMonEntier ;

Supposons que pointeurSurMonEntier reprsente l'adresse de la variable monEntier.


An de relier ces deux lments, nous allons utiliser le signe & :
1
2

int monEntier = 10 ;
int * pointeurSurMonEntier = & monEntier ;

Tout comme les variables, les pointeurs ont un type. Ici par exemple,
*pointeurSurMonEntier est de type int, c'est--dire du mme type que la
variable laquelle il fait rfrence. Cette remarque se gnralise : un pointeur
est toujours du mme type que la variable sur laquelle il pointe.

Il est possible de modier la valeur d'une variable en agissant sur son pointeur. Par
exemple, pour aecter la valeur 25 la variable monEntier, on peut utiliser indiremment les deux instructions suivantes :
1
2

monEntier = 25 ;
* pointeursurMonEntier = 25 ;

Chanes de caractres
Les chanes de caractres sont composes de zro, un ou plusieurs caractres. Comme il
a t vu un peu plus tt, les variables et constantes de type char ne peuvent mmoriser
qu'un et un seul caractre. Pour mmoriser des chanes, nous utiliserons des pointeurs
de char.
Qu'est-ce encore que cela ?

Les pointeurs de char sont des zones mmoire qui mmorisent l'emplacement d'une
suite de zro, un ou plusieurs char. C'est prcisment ce que sont les chanes de caractres. Les pointeurs de char sont donc particulirement bien adapts leur dnition.
titre d'exemple, l'instruction suivante dnit la chane nom et l'initialise avec une
chane de caractres :
1

56

char * nom = " Mon nom est Bond , James Bond " ;

LES POINTEURS

Structures
Jusqu'ici, nous avons tudi des types de donnes  simples  : boolens, entiers, ottants, doubles, caractres et chanes de caractres. Il est parfois ncessaire de regrouper plusieurs informations disparates dans une seule et mme variable. Imaginez par
exemple que vous dsiriez mmoriser le prnom, le nom et l'ge de plusieurs personnes.
Le plus simple consiste regrouper ces informations dans une structure en utilisant
l'instruction struct :
1
2
3
4
5
6

struct unePersonne
{
char * prenom ;
char * nom ;
int age ;
};

Une fois cette structure dnie, on peut dnir une variable de type unePersonne et
accder ses direntes composantes en utilisant des instructions  point . Par
exemple :
1
2
3
4

struct unePersonne schwarzi ;


schwarzi . prenom = " Arnold " ;
schwarzi . nom = " Schwarzenegger " ;
schwarzi . age = 64 ;

Conversions de type
Dans votre vie de programmeur Objective-C, vous serez souvent amens convertir
une variable d'un certain type en une variable d'un autre type. En eet, les types des
variables manipules doivent tre exactement ceux attendus dans le langage, sans quoi
une erreur se produira et il sera impossible d'excuter le programme.
La conversion peut tre  implicite  (c'est--dire sans ncessiter l'intervention du programmeur) ou  explicite  (c'est--dire en utilisant un oprateur de conversion).
Conversion implicite

Examinons les quelques lignes de code suivantes :


1
2
3
4

int a
float
int c
float

=
b
=
d

10 ;
= 13 . 562 ;
a * b;
= a * b;

Le produit de a par b est gal 135.62. Cette valeur est de type ottant puisqu'elle
comporte des dcimales.
Quelles valeurs auront les variables c et d selon vous ?
57

CHAPITRE 4.

LES BASES DE L'OBJECTIVE-C

la ligne 3, lorsque la valeur 135.62 est stocke dans la variable entire c, elle est
 tronque  (c'est--dire prive de ses dcimales) 135. L'instruction int c = a *
b; a eectu une conversion implicite du type float vers le type int an que le rsultat
puisse tre mmoris dans la variable entire c.
Par contre, dans la ligne 4, lorsque la valeur 135.62 est stocke dans la variable ottante
d, elle est gale 135.62.
Conversion explicite

Pour eectuer une conversion explicite (on dit aussi un casting ), il sut de prciser le
type vis entre parenthses avant la valeur convertir.
1
2
3
4

int a = 10 ;
float b = 13 . 562 ;
float c = a * ( long int ) b ;
NSLog ( @ " % f " ,c ) ;

Est-il possible d'avoir quelques explications sur la ligne 3 ?

La variable b est de type float, puisqu'elle est dclare comme telle la ligne 2. Le
casting (long int)b convertit la valeur de la variable b en un long int. Cette valeur
est ensuite multiplie par la valeur contenue dans la variable a, de type int. Le rsultat
est donc de type long int. Enn, ce rsultat est stock dans la variable c de type float
(float c =). Il est donc converti dans le type float.
Quel rsultat sera ach par l'instruction NSLog selon vous ? Le casting de b en un
long int donne la valeur entire 13. Le rsultat de la multiplication est donc 130.
Mais tant donn que ce rsultat est stock dans une variable float, NSLog achera
130.000000.
Pour aller un peu plus loin, nous allons nous intresser un autre exemple, bas sur
l'utilisation d'un code ASCII.
Code ASCII ? Mais qu'est-ce donc que cela ?

ASCII est l'abrviation de American Standard Code for Information Interchange. Il


s'agit d'une norme d'encodage des caractres alphanumriques de l'alphabet latin. Ainsi
par exemple, le nombre 64 reprsente le caractre  @ , le nombre 65 reprsente le
caractre  A , le nombre 66 reprsente le caractre  B , et ainsi de suite. Pour avoir
de plus amples informations sur le codage ASCII, je vous suggre de vous reporter
la table ASCII accessible grce au code web suivant.


Table
ASCII
B
Code web : 277885


58

LES POINTEURS

Voici notre exemple :


1
2
3

int i = 65 ;
char c = ( char ) i;
NSLog ( @ " % c " , c ) ;

En lui appliquant un casting de type (char), la variable char c est initialise avec le
caractre A. C'est donc ce qu'ache l'instruction NSLog. L'entier 65 est donc quivalent
au caractre A.

En rsum
 Une variable permet de stocker temporairement des informations dans la mmoire
de votre device et d'y accder par la suite.
 Pour dnir une variable, vous utiliserez l'instruction suivante : type nomVariable;.
 Il est possible d'aecter directement une valeur une variable lors de sa dnition :
type nomVariable = valeur;.
 Pour dnir une constante, utilisez la syntaxe suivante : const type nomConstante
= valeur;.
 Un certain nombre de traitements peuvent tre appliqus aux variables par l'intermdiaire d'oprateurs. On distingue essentiellement les oprateurs d'aectation (=,
+=, -=, /=, *= et %=) et les oprateurs arithmtiques (+, -, ++, --, *, / et %).
 Les commentaires peuvent occuper une seule ligne. Dans ce cas, ils sont prcds
d'un double slash (//). Ils peuvent galement s'taler sur plusieurs lignes. Dans ce
cas, ils commencent par les caractres /* et se terminent par les caractres */.
 Les variables sont caractrises par leur type : boolen, entier, rel, caractre, chane,
pointeur et structure.
 Les conversions de types peuvent tre implicites (lors de la dnition d'une variable)
ou explicites (en prcisant le type recherch entre parenthses avant la valeur
convertir).

59

CHAPITRE 4.

60

LES BASES DE L'OBJECTIVE-C

Chapitre

Conditions, boucles et fonctions


Dicult :

ans ce chapitre, vous allez aller un peu plus loin dans la programmation Objective-C.
Au l des pages, vous apprendrez :
 eectuer des tests pour excuter une ou plusieurs instructions si une condition est remplie ;
 faciliter la rptition d'instructions ;
 dnir et excuter des fonctions pour excuter des tches bien prcises.
a n'a l'air de rien comme a, mais la n de ce chapitre vous serez capables de crer de
petits programmes.

61

CHAPITRE 5.

CONDITIONS, BOUCLES ET FONCTIONS

Conditions
En programmation, on utilise des conditions pour tester la valeur des variables. Selon
le rsultat obtenu, zro, une ou plusieurs instructions peuvent alors tre excutes.
Avant de nous intresser aux conditions, nous allons passer un peu de temps avec les
oprateurs de comparaison. En eet, ces oprateurs sont trs souvent utiliss dans des
conditions. Par exemple pour savoir si une variable est suprieure une autre, ou encore
si une variable est gale zro.

Oprateurs de comparaison
Les oprateurs de comparaison (dits logiques) sont trs importants. Ils permettent de
comparer des valeurs entre elles. Par leur intermdiaire, vous pourrez savoir qui de
Pierre ou de Jean est le plus grand, ou encore si les prunes sont plus chres au kilo que
les bananes. J'ai regroup tous les oprateurs logiques dans le tableau suivant.
Oprateur Signication
!
<
>
==
<=
>=
!=
&&
||
^

Non
Infrieur
Suprieur
gal
Infrieur ou gal
Suprieur ou gal
Dirent de
Et logique (vrai si les deux oprandes ont pour valeur true)
Ou logique (vrai si au moins un des deux oprandes a pour valeur true)
Ou exclusif (vrai si un seul des deux oprandes a pour valeur true)

Remarquez le double signe gal (==), pour indiquer qu'il s'agit d'un test et
non d'une aectation.

Maintenant, nous allons mettre en pratique les oprateurs de comparaison en les utilisant dans des conditions.

if
Pour tester une condition, l'oprateur de base est le if (  si  en franais). Par exemple,
imaginez que la variable pointure contienne une pointure de chaussure. Si la pointure
est infrieure ou gale 30, vous voulez acher un message qui dit  Vous devez vous
chausser au rayon enfants . Vous crirez ceci :
1
2

62

if ( pointure <= 30 )
{

CONDITIONS

3
4

NSLog ( @ " Vous devez vous chausser au rayon enfants " ) ;

Si la condition est vrie (si la variable pointure est infrieure ou gale 30), alors
ce qui se trouve entre les accolades sera excut. Les plus observateurs d'entre vous
auront sans doute remarqu que la condition ainsi que les accolades la dlimitant ne se
terminent pas par un  ; . C'est tout fait normal, ce ne sont pas des instructions.
Bien entendu, il est possible d'excuter plusieurs instructions :
1
2
3
4
5
6

if ( pointure <= 30 )
{
NSLog ( @ " Vous avez de petits pieds " ) ;
NSLog ( @ " Vous devez vous chausser au rayon enfants " ) ;
// etc .
}

Si une seule instruction se trouve entre les accolades, ces dernires sont facultatives.
1
2

if ( pointure <= 30 )
NSLog ( @ " Vous devez vous chausser au rayon enfants " ) ; // Ici
les accolades sont facultatives

Que diriez-vous d'un peu de pratique ?


Ouvrez le projet de test cr au chapitre prcdent. Si vous ne l'avez plus, pas de
panique, vous pouvez en crer un nouveau, il fera aussi bien l'aaire.
Cliquez sur ViewController.m dans le volet de navigation et compltez la mthode
viewDidLoad comme suit :
1
2
3
4
5
6
7
8
9
10

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
int pointure = 29 ;
if ( pointure <= 30 )
{
NSLog ( @ " Vous avez de petits pieds " ) ;
NSLog ( @ " Vous devez vous chausser au rayon enfants " ) ;
}
}

la ligne 4, la variable pointure est initialise 29. Mais rien ne vous empche de
choisir une autre valeur.
Excutez l'application en cliquant sur Run. Si ncessaire, achez le volet de dbogage
en cliquant sur Hide or show the Debug area. Voici ce qui devrait s'acher dans le
volet de dbogage :
63

CHAPITRE 5.

CONDITIONS, BOUCLES ET FONCTIONS

Attaching to process 877.


[...] test [877: f803 ] Vous avez de petits pieds
[...] test [877: f803 ] Vous devez vous chausser au rayon enfants

Ici, le processus 877 est attach l'application. Sur votre ordinateur, le processus sera dirent. Ceci est tout fait normal. Notez galement que j'ai
masqu l'heure et la date, ce n'est pas ce qui nous intresse ici. Ne soyez
donc pas tonns si vous rencontrez encore des  [...] .

else
Il arrive parfois que l'on doive excuter une instruction si une condition est remplie,
et une autre instruction dans le cas contraire. Pour cela, on a recours au mot-cl else
(c'est--dire  sinon  en franais) :
1
2
3
4

if ( pointure <= 30 )
NSLog ( @ " Vous devez vous chausser au rayon enfants " ) ;
else
NSLog ( @ " Vous devez vous chausser au rayon adultes " ) ;

else if
Imaginez maintenant que vous vouliez excuter :
 une premire instruction si la pointure est infrieure ou gale 30 ;
 une deuxime instruction si la pointure est suprieure 45 ;
 une troisime instruction si la pointure ne rpond aucune de ces deux conditions.
Pour cela, vous utiliserez les mots-cls if (si), else if (sinon si) et else (sinon) :
1
2
3
4
5
6

if ( pointure <= 30 )
NSLog ( @ " Vous devez vous chausser au rayon enfants " ) ;
else if ( pointure > 45 )
NSLog ( @ " Vous devez vous chausser sur mesure " );
else
NSLog ( @ " Vous devez vous chausser au rayon adultes " ) ;

Il est bien videmment possible d'utiliser plusieurs else if. Vous pourriez trs bien
crire quelque chose comme ceci, mme si l'intrt de ce code est limit :
1
2
3
4
5
6
7
8

64

if ( pointure <= 30 )
NSLog ( @ " Vous devez vous chausser au rayon enfants " ) ;
else if ( pointure == 36 )
NSLog ( @ " Vous chaussez du trente - six " ) ;
else if ( pointure == 37 )
NSLog ( @ " Vous chaussez du trente - sept " ) ;
else if ( pointure == 38 )
NSLog ( @ " Vous chaussez du trente - huit " ) ;

CONDITIONS

N'hsitez pas tester ce code (n'oubliez pas de dclarer votre variable pointure) en
changeant ses valeurs. C'est comme a qu'on apprend !

Plusieurs conditions dans un test


Les oprateurs logiques && (et), || (ou) et ! (non) peuvent tre utiliss dans une condition. Par exemple, pour tester si la pointure est suprieure 35 et infrieure 42, vous
crirez ceci :
1

if ( pointure > 35 && pointure < 42 )

D'aprs vous, que devriez-vous crire pour tester si la pointure est comprise entre 35
et 42, mais dirente de 40. Je vous laisse quelques instants. . .
Voil la solution :
1

if ( pointure > 35 && pointure < 42 && pointure != 40 )

Facile, non ?
Il est parfois ncessaire d'utiliser des parenthses dans un test complexe pour modier
l'ordre d'excution des lments qui composent le test. Par exemple, les deux tests
suivants ne sont pas quivalents :
1
2

if (( a + 3 ) / 4 < 10 )
if ( a + 3 / 4 < 10 )

Le premier test ajoute 3 la variable a, divise cette somme par 4 et compare le rsultat
obtenu 10. Le deuxime test ajoute 3/4 la variable a et compare le rsultat obtenu
10.
titre d'information, voici l'ordre d'excution des principaux oprateurs, du plus prioritaire au moins prioritaire :
Nom

Parenthses
Oprateur de changement de signe
Oprateurs ++ et -- utiliss en prxe
Ngation
Multiplication, division et modulo
Addition et soustraction
Infrieur, infrieur ou gal, suprieur, suprieur ou gal
gal, dirent de
Et logique
Ou logique
Aectation

Oprateur
()
++ et -!
*, / et %
+ et <, <=, >, >=
== et !=
&&
||
=

65

CHAPITRE 5.

CONDITIONS, BOUCLES ET FONCTIONS

L'instruction switch
Il existe une variante de l'instruction if...
Voici sa syntaxe :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

switch ( variable )
{
case valeur1 :
une ou plusieurs
break ;
case valeur2 :
une ou plusieurs
break ;
case valeur3 :
une ou plusieurs
break ;
...
default :
une ou plusieurs
break ;
}

else if... else... : l'instruction switch.

instructions ;
instructions ;
instructions ;

instructions ;

O :
 variable est la variable utilise dans le test ;
 les case valeur1:, case valeur2:, etc. correspondent aux valeurs tester ;
 une ou plusieurs instructions; sont des instructions dnies sur une ou plusieurs lignes ;
 les instructions situes aprs le mot default sont excutes lorsqu'aucune des conditions spcies dans les instructions case n'a t vrie ;
 break marque la n des instructions qui suivent une instruction case ou default.
L'instruction switch est un peu plus complexe que celles que nous avons vues jusqu'ici.
Un exemple va vous aider en comprendre le fonctionnement.
Considrez le test suivant :
1
2
3
4
5
6
7
8
9
10

if ( pointure == 30 )
NSLog ( @ " Vous devez vous chausser au rayon enfants " ) ;
else if ( pointure == 36 )
NSLog ( @ " Vous chaussez du trente - six " ) ;
else if ( pointure == 37 )
NSLog ( @ " Vous chaussez du trente - sept " ) ;
else if ( pointure == 38 )
NSLog ( @ " Vous chaussez du trente - huit " ) ;
else
NSLog ( @ " Vous ne chaussez pas du 30 , 36 , 37 ou 38 " ) ;

Vous pourriez tout aussi bien crire :


1
2
3

66

switch ( pointure )
{
case 30 :

BOUCLES

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

NSLog ( @ " Vous


break ;
case 36 :
NSLog ( @ " Vous
break ;
case 37 :
NSLog ( @ " Vous
break ;
case 38 :
NSLog ( @ " Vous
break ;
default :
NSLog ( @ " Vous
break ;

devez vous chausser au rayon enfants " ) ;


chaussez du trente - six " ) ;
chaussez du trente - sept " ) ;
chaussez du trente - huit " ) ;
ne chaussez pas du 30 , 36 , 37 ou 38 " ) ;

Encore une fois, n'hsitez pas tester ce code en modiant ses valeurs.

Boucles
En programmation, il est souvent ncessaire d'excuter plusieurs reprises une instruction ou un groupe d'instructions, par exemple tant qu'une condition n'est pas vrie.
Supposons que vous vouliez acher dix reprises le mot  Bonjour . Comment vous
y prendriez-vous ? La premire ide qui vient l'esprit consiste rpter dix fois l'instruction d'achage NSLog :
1
2
3
4
5
6
7
8
9
10

NSLog ( @ " Bonjour " ) ;


NSLog ( @ " Bonjour " ) ;
NSLog ( @ " Bonjour " ) ;
NSLog ( @ " Bonjour " ) ;
NSLog ( @ " Bonjour " ) ;
NSLog ( @ " Bonjour " ) ;
NSLog ( @ " Bonjour " ) ;
NSLog ( @ " Bonjour " ) ;
NSLog ( @ " Bonjour " ) ;
NSLog ( @ " Bonjour " ) ;

Imaginez maintenant que vous vouliez rpter 100 fois l'achage du mot  Bonjour .
Allez-vous crire cent fois la mme instruction ? Heureusement non ! Il existe plusieurs
solutions bien plus lgantes : vous utiliserez pour cela une boucle for, while ou do
while.
Dans tous les cas, la procdure est la mme. Regardez la gure 5.1, elle reprsente le
fonctionnement d'une boucle.
Voici ce qui se passe :
 l'ordinateur lit les instructions de haut en bas ;
 arriv la n de la boucle, il retourne la premire instruction ;
67

CHAPITRE 5.

CONDITIONS, BOUCLES ET FONCTIONS

Figure 5.1  Schma d'une boucle

 il lit de nouveau les instructions de haut en bas ;


 il repart la premire instruction ;
 etc.
Malheureusement il y a un problme : la boucle est innie ! Si on ne l'arrte pas,
l'ordinateur va lire les instructions ad vitam ternam. Heureusement, les conditions
vont nous aider. Lorsqu'on cre une boucle, on indique une condition pour sortir de la
boucle.

La boucle for
La boucle for est l pour vous viter une luxation du poignet. Voici sa syntaxe :
1
2
3
4

for ( d but ; fin ; incr ment )


{
// Une ou plusieurs instructions
}

Trois paramtres sont passs la boucle for :


 dbut reprsente la valeur initiale du compteur de boucle ;
 fin reprsente la condition qui permet de dcider si la boucle se poursuit ou se
termine ;
 incrment modie la valeur du compteur de boucle la n de chaque tour de boucle.
Tout ceci vous semble peut-tre obscur. Rassurez-vous, un petit exemple va vite clarier
les choses. Considrez le code suivant :
1
2
3
4
5

int compteur ;
for ( compteur = 0 ; compteur < 100 ; compteur ++)
{
NSLog ( @ " Bonjour " ) ;
}

Lors de la premire excution de la boucle, la variable entire compteur est initialise


0. La condition compteur < 100 est alors vrie, puisque 0 < 100. L'instruction
NSLog est excute, l'ordinateur repart au dbut de la boucle.
Lors de la deuxime excution de la boucle, le compteur est incrment de 1 (compteur++).
Il a donc pour valeur 1. La condition tant vrie (1 < 100), l'instruction NSLog est
de nouveau excute.
68

BOUCLES

Ainsi de suite, jusqu' ce que compteur soit gal 100. Dans ce cas, la boucle for
prend n et le programme continue de s'excuter. Si vous faites le compte, l'instruction
NSLog aura t excute. . . 100 fois, ce qui est exactement l'eet recherch.
tant donn qu'une seule instruction est excute dans la boucle for, les accolades ne
sont pas obligatoires. Dans notre exemple, vous auriez donc tout aussi bien pu crire :
1
2

for ( compteur = 0 ; compteur < 100 ; compteur ++)


NSLog ( @ " Bonjour " ) ;

Que diriez-vous d'un peu de pratique ?


Toujours dans votre projet test, cliquez sur ViewController.m dans le volet de navigation. Reprez la mthode viewDidLoad et compltez-la comme suit :
1
2
3
4
5
6
7

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
int compteur ;
for ( compteur = 0 ; compteur < 100 ; compteur ++)
NSLog ( @ " Bonjour " ) ;
}

Excutez l'application en cliquant sur Run. Trs rapidement, cent lignes contenant le
mot  Bonjour  sont aches dans le volet de dbogage :
Attaching to process 2440.
[...] test [2440: f803 ] Bonjour
...
[...] test [2440: f803 ] Bonjour

La boucle while
La boucle while est une variante de l'instruction for. Elle excute une ou plusieurs
instructions tant qu'une condition est vrie. Voici sa syntaxe :
1
2
3
4

while ( condition )
{
// Une ou plusieurs instructions
}

Voyons comment rsoudre notre problme prcdent avec une boucle while.
1
2
3
4
5
6

int compteur = 0 ;
while ( compteur < 100 )
{
NSLog ( @ " Bonjour " ) ;
compteur ++;
}

La premire instruction initialise 0 la variable compteur.


69

CHAPITRE 5.

CONDITIONS, BOUCLES ET FONCTIONS

La boucle while se poursuit jusqu' ce que la variable compteur soit suprieure ou


gale 100 (while (compteur < 100)). Lors de l'entre dans la boucle, compteur
vaut 0.
Les instructions entre les accolades sont donc excutes : la premire ache le texte
 Bonjour , la deuxime incrmente d'un la variable compteur, qui vaut alors 1.
Aprs l'incrmentation, la condition compteur < 100 est toujours vrie, puisque
compteur vaut 1. Les instructions l'intrieur des accolades sont donc excutes une
nouvelle fois.
Ainsi de suite jusqu' ce que compteur soit gal 100.
N'hsitez pas tester le fonctionnement de la boucle while. Dans votre projet test,
reprez la mthode viewDidLoad et compltez-la comme suit :
1
2
3
4
5
6
7
8
9
10

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
int compteur = 0 ;
while ( compteur < 100 )
{
NSLog ( @ " Bonjour " ) ;
compteur ++;
}
}

Excutez l'application en cliquant sur Run pour constater que cent lignes contenant le
mot  Bonjour  sont aches dans le volet de dbogage.
Vous pouvez vous amuser modier la condition initiale du compteur (ligne 4) et la
limite suprieure du compteur (ligne 5). Relancez l'application pour voir l'eet rsultant.
Attention ne pas crer une boucle innie, ou simplement trop grosse :
rpter un mot 100 fois est facile pour votre ordinateur ; le rpter 100 000
000 devient dj plus dicile pour lui. Et bien souvent il plante.

La boucle do while
La boucle do while est une variante de l'instruction while. Mais ici, la condition
est teste aprs l'excution des instructions entre accolades. Dans tous les cas, les
instructions entre les accolades seront donc excutes au moins une fois. Voici la syntaxe
de cette instruction :
1
2
3
4

70

do
{

// Une ou plusieurs instructions


} while ( condition ) ;

FONCTIONS

Si on voulait adapter notre exemple prcdent, voici comment il faudrait faire avec une
boucle do while :
1
2
3
4
5
6

int compteur = 0 ;
do
{
NSLog ( @ " Bonjour " ) ;
compteur ++;
} while ( compteur < 100 );

La premire instruction initialise la variable compteur 0. Les instructions entre les


accolades sont alors excutes une premire fois : le mot  Bonjour  est ach avec la
fonction NSLog() et la variable compteur est incrmente de 1.
La condition la suite du while est alors examine. Aprs la premire excution des
instructions entre les accolades, compteur vaut 1. Il est donc bien infrieur 100 et la
boucle se poursuit. Ainsi de suite jusqu' ce que compteur devienne gal 100.

Fonctions
Une fonction peut tre compare une bote dont l'intrieur ne peut tre vu. On
lui fournit (ventuellement) une ou plusieurs donnes, elle eectue un traitement et
retourne (ventuellement) une ou plusieurs autres donnes (gure 5.2).

Figure 5.2  Schma de fonctionnement d'une fonction

Une fonction consiste donc en un ensemble d'instructions qui eectuent un traitement


et transforment les donnes qui lui sont fournies en d'autres donnes.
Dcouper le code d'une application en plusieurs fonctions prsente plusieurs avantages :
chaque fonction tant indpendante du reste du code, il est facile de la tester et de la
faire voluer au grs des direntes versions de l'application.
Pour dclarer une fonction, vous utiliserez la syntaxe suivante :
1
2
3
4
5

type nom ( param tres )


{
// Une ou plusieurs instructions
return retour ;
}

O :
 type indique le type de la donne retourne par la fonction (int, float, etc.) ;
71

CHAPITRE 5.

CONDITIONS, BOUCLES ET FONCTIONS

 nom est le nom de la fonction ;


 paramtres reprsente les ventuelles donnes fournies la fonction ;
 retour reprsente la donne renvoye par la fonction.
La fonction nom utilise le ou les paramtres qui lui sont fournis pour eectuer un
traitement et retourner la donne retour.
L'appel d'une fonction n'a rien de bien compliqu : il sut d'indiquer son nom, ventuellement suivi des paramtres qui doivent lui tre passs. Si la fonction renvoie une
valeur, vous l'aecterez une variable du mme type que la valeur renvoye.
titre d'exemple, la fonction ttc ci-aprs renvoie le prix TTC correspondant au prix
HT qui lui est pass. Le prix HT et le prix TTC sont de type float.
1
2
3
4

float ttc ( float ht )


{
return ht * 1 . 196 ;
}

Ici, un paramtre de type float doit tre fourni la fonction (le prix HT), qui renvoie
une valeur de type float. L'instruction utilise sera donc du type suivant (ici, nous
calculons la valeur TTC correspondant un prix HT de 100) :
1

float lePrixTTC = ttc ( 100 ) ;

Il est possible d'aller plus loin ! Supposons que la fonction ttc doive calculer deux types
de prix TTC : un avec une TVA de 5,5 %, un autre avec une TVA de 19,6 %. Comment
devriez-vous complter la fonction ttc prcdente ? Je vous laisse rchir.
...
Si c'est vraiment trop dicile pour vous, je vais vous mettre sur la voie.
 La fonction va avoir besoin de connatre le prix HT et la TVA appliquer. Ces
lments seront passs la fonction sous la forme de paramtres, donc entre les
parenthses. La TVA peut tre fournie la fonction telle quelle, au format float,
ou reprsente par un nombre int, qui pourrait valoir 1 dans le cas d'une TVA
5,5 % et 2 dans le cas d'une TVA 19,6 %.
 Dans la fonction, il faudra eectuer un calcul ou un autre en fonction du taux de
TVA appliquer. Une instruction if semble donc tout fait approprie.
Cette fois-ci, je vous laisse vraiment rchir. Vous avez tous les lments pour crire
cette fonction.
Voici le code que je vous propose :
1
2
3
4
5
6
7

72

float ttc ( float ht , int tva )


{
if ( tva == 1 )
return ht * 1 . 055 ;
else
return ht * 1 . 196 ;
}

FONCTIONS

Le code que je vous propose n'est pas le code. En programmation, il y a


direntes faons d'arriver un mme rsultat. Si votre code dire du mien
mais qu'il fait la mme chose, c'est trs bien.

La fonction ttc a maintenant deux paramtres : le prix HT et la TVA. Le deuxime


paramtre est de type int. S'il est gal 1, la fonction ttc renverra un prix TTC
calcul avec une TVA de 5,5 %. Dans tous les autres cas, la fonction ttc renverra un
prix TTC calcul avec une TVA de 19,6 %.
Et pour appeler la fonction :
1
2

float prix1 = ttc ( 100 , 1 ) ; // Prix HT de 100 et TVA 5 , 5 %


float prix2 = ttc ( 100 , 2 ) ; // Prix HT de 100 et TVA 19 , 6 %

Une fonction peut ne pas avoir de paramtre et peut aussi ne rien retourner.
Dans ce cas, le mot-cl void est utilis pour remplacer les paramtres et/ou
le retour.

Par exemple, une fonction qui ache le mot  Bonjour  dans le volet de dbogage
ne demande aucun paramtre et ne retourne aucune valeur. Elle pourrait avoir l'allure
suivante :
1
2
3
4

void bonjour ( void )


{
NSLog ( @ " Bonjour \ n " ) ;
}

En rsum
 Pour comparer des valeurs entre elles, on utilise des oprateurs logiques.
 Pour tester une condition, on utilise if, else if et else.
 Il est possible d'eectuer plusieurs conditions dans un test, en sparant ces conditions
par un oprateur logique.
 switch est quivalent if... elseif... else.... Cela permet de comparer une
variable avec plusieurs valeurs et d'excuter une ou plusieurs instructions en consquence.
 Pour rpter un certain nombre de fois une ou plusieurs instructions, vous utiliserez
une boucle for, while ou do while. La boucle for est particulirement bien adapte
lorsque l'on connat le nombre d'itrations de la boucle. Les instructions while et do
while prennent n lorsqu'une condition logique est vrie.
 Une fonction consiste en un ensemble d'instructions qui eectuent un traitement et
transforment les donnes qui lui sont fournies en d'autres donnes. Pour dnir une
fonction, prcisez son type, la ou les variables qui lui sont passes en paramtre et
utilisez return pour retourner une valeur. Pour appeler une fonction, indiquez son
nom et passez-lui une ou plusieurs variables entre parenthses.
73

CHAPITRE 5.

74

CONDITIONS, BOUCLES ET FONCTIONS

Chapitre

La programmation oriente objet


Dicult :

ans ce chapitre, vous allez dans un premier temps dcouvrir ce qui se cache derrire la
programmation oriente objet (POO). Vous verrez ensuite comment mettre en uvre
ce type de programmation en utilisant le langage Objective-C.
La programmation oriente objet est une notion dicile comprendre, aussi n'hsitez pas
lire ce chapitre plusieurs fois, tte repose. Vous verrez, cela devrait nir par rentrer !

75

CHAPITRE 6.

LA PROGRAMMATION ORIENTE OBJET

Qu'est-ce que la programmation oriente objet ?


Dans la programmation  traditionnelle , les programmes sont constitus d'un ensemble d'instructions qui s'excutent les unes la suite des autres (voir gure 6.1).

Figure 6.1  Les instructions s'excutent les unes la suite des autres

Dans la plupart des programmes, on dnit une boucle qui ne fait rien d'autre qu'attendre l'arrive d'un vnement. Par exemple, la n d'un calcul, un changement d'heure,
un clic souris ou un autre type d'vnement quelconque. Si aucun vnement ne se produit, la boucle se contente d'attendre, encore et encore. C'est pourquoi on l'appelle
souvent  boucle d'attente . Si un vnement survient, il est identi et trait en
consquence. La gure 6.2 illustre mes propos.

Figure 6.2  Dans la plupart des programmes, on attend un vnement

76

QU'EST-CE QUE LA PROGRAMMATION ORIENTE OBJET ?

Dans la programmation oriente objet, les programmes sont constitus d'un ensemble
de blocs de code indpendants appels objets. Chaque objet contient sa propre boucle
d'attente. Lorsqu'un vnement concernant un objet particulier survient, c'est cet
objet de traiter l'vnement, comme le montre la gure 6.3.

Figure 6.3  Avec la POO, ce sont les objets qui traitent les vnements

Les langages orients objet utilisent plusieurs termes techniques bien particuliers. Pour
vous aider les apprhender, je vais utiliser une analogie en me basant sur des objets
courants de la vie de tous les jours : des voitures.
Une voiture est dnie par un ensemble de caractristiques : modle et couleur entre
autres. Elle est fabrique dans une usine. Lors de la fabrication, une ou plusieurs options
sont ajoutes au modle de base.
Dans un langage orient objet :
 l'usine est une classe : c'est elle qui fabrique les objets ;
 la voiture est un objet ;
 les caractristiques de la voiture sont des proprits ;
 les options sont des mthodes de la classe Usine.
Je vous ai fait un schma en gure 6.4 pour vous aider mieux visualiser tout a.
Maintenant que vous avez le vocabulaire ncessaire, nous allons rentrer dans le vif du
sujet.

77

CHAPITRE 6.

LA PROGRAMMATION ORIENTE OBJET

Figure 6.4  Une voiture est un objet

78

DFINIR UNE CLASSE

Dnir une classe


Revenons au petit monde des devices Apple. Une application iOS est btie autour
d'une classe qui contient un ensemble d'objets, de proprits (qui reprsentent l'tat
des objets) et de mthodes (qui rgissent le fonctionnement des objets) (voir gure 6.5)
.

Figure 6.5  Une application iOS est btie autour d'une classe qui contient un ensemble

d'objets, de proprits et de mthodes

Supposons que vous vouliez dnir la classe maClasse (oui, je sais, c'est trs original !).
Vous devrez agir dans deux chiers distincts : maClasse.h et maClasse.m.
 maClasse.h est un chier d'en-ttes. Il est utilis pour dclarer les lments manipuls dans le code.
 maClasse.m contient le code source de l'application.
79

CHAPITRE 6.

LA PROGRAMMATION ORIENTE OBJET

Le chier .h
Pour interagir avec ses utilisateurs, une application utilise une interface. Dans une
application iOS, cette interface peut contenir du texte, des images, des vidos, des
boutons et bien d'autres choses encore. En tant que programmeur, vous devrez utiliser
des classes pour dnir ces dirents lments. Bien qu'il soit possible de dnir
partir de zro tous ces lments (forme, ombrage, couleur, comportement sur l'cran
etc.), vous prfrerez sans aucun doute utiliser des classes toutes faites. Pour faciliter la
vie des dveloppeurs, Apple a eu la bonne ide de regrouper ces classes dans une sorte
de bote outils (on dit aussi framework) appele UIKit. C'est par son intermdiaire
que vous pourrez ajouter du texte, des images, des boutons, des vidos, etc. vos
applications.
Pour tablir le lien entre l'application en cours de dveloppement et le framework
UIKit, la premire instruction d'un chier .h doit toujours tre la suivante :
1

# import < UIKit / UIKit .h >

Cette simple instruction donne accs toutes les classes du framework UIKit.
Les lignes qui suivent l'instruction #import dnissent le nom et le type de l'application,
ainsi que les variables utilises dans l'application :
1
2
3
4

@interface nom : type


{
Une ou plusieurs variables
}

O nom est le nom de l'application et type dnit son type.


Je sais pertinemment qu'arrivs ce point du livre, vous n'avez aucune ide
de ce que peut tre le type d'une application iOS. N'ayez crainte, ce n'est
pas important pour l'instant. L'exemple qui suit repose sur une application de
type UIViewController. J'aurais tout aussi bien pu choisir une application
de type  Schmoldu , mais j'ai prfr coller la ralit en utilisant un type
existant.

Supposons donc que vous dnissiez l'application test de type UIViewController.


L'instruction @interface aura l'allure suivante :
1
2
3
4

@interface testViewController : UIViewController


{
// Une ou plusieurs variables
}

Les variables dnies entre les accolades sont appeles variables d'instance.
Qu'est-ce encore que cela ?

80

DFINIR UNE CLASSE

Quand vous dveloppez une application iOS, vous dnissez une nouvelle classe. Lorsque
l'application est lance, on dit qu'une  instance de la classe  est cre. Cela signie
qu'un objet de cette classe est cr. Les variables d'instance sont propres cette instance : si vous lancez deux fois l'application, les variables utilises dans la premire
instance ne seront pas lies la seconde, et inversement. Si vous avez du mal comprendre, la gure 6.6 devrait vous clairer.

Figure 6.6  Chaque instance de classe a des variables qui lui sont propres

Voici un exemple de chier d'en-ttes .h :


1
2
3
4
5
6
7

# import < UIKit / UIKit .h >


@interface Voiture : NSObject {
NSString * modele ;
NSString * couleur ;
}
@end

La classe a pour nom Voiture. Le chier qui dnit l'interface a donc pour nom
Voiture.h.
La classe Voiture possde deux variables d'instance NSString : modele et couleur.
Pas si vite ! Qu'est-ce que signie NSString et pourquoi y a-t-il un astrisque
aprs ce mot ?
NSString

reprsente le type des variables modele et couleur. Il s'agit d'un type per81

CHAPITRE 6.

LA PROGRAMMATION ORIENTE OBJET

mettant de manipuler des chanes de caractres. L'astrisque indique que les variables
modele et couleur sont des pointeurs de NSString. Elles contiendront donc l'adresse
des chanes et non les chanes elles-mmes. Comme vous le verrez tout au long de ce
livre, l'utilisation de pointeurs dans Objective-C est monnaie courante.
Dnir des variables d'instance, c'est bien, mais pouvoir y accder, c'est mieux ! En
eet, les variables d'instance sont l pour mmoriser des donnes, et ces donnes doivent
pouvoir tre crites dans les variables d'instance et lues depuis les variables d'instance.
Pour accder aux variables d'instance, nous allons ajouter des getters (pour connatre
la valeur stocke dans les variables) et des setters (pour stocker des valeurs dans les
variables et y accder) :
1
2
3
4

( NSString *) modele ;
( NSString *) couleur ;
( void ) setModele : ( NSString *) input ;
( void ) setCouleur : ( NSString *) input ;

Les deux premires instructions sont des getters. Elles permettent de lire les valeurs stockes dans les variables d'instance modele et couleur ; en d'autres termes, de connatre
le modle et la couleur de la voiture. La valeur renvoye est de type NSString. Au dbut
de ces deux lignes, le signe - indique qu'il s'agit de mthodes d'instance.
Les deux dernires lignes sont des setters. Elles permettent de stocker des valeurs dans
les variables d'instance modele et couleur, c'est--dire dnir le modle et la couleur
de la voiture. Ici aussi, il s'agit de mthodes d'instance, d'o le signe - au dbut des
instructions. Ces mthodes ne renvoient aucune valeur, ce qui explique le (void) au
dbut des instructions.
Le chier d'en-ttes est maintenant complet. Voici les instructions qui le composent :
1
2
3
4
5
6
7
8
9
10
11

# import < UIKit / UIKit .h >


@interface Voiture : NSObject {
NSString * modele ;
NSString * couleur ;
}
- ( NSString *) modele ;
- ( NSString *) couleur ;
- ( void ) setModele : ( NSString *) input ;
- ( void ) setCouleur : ( NSString *) input ;
@end

Le chier .m
Nous allons maintenant implmenter (c'est--dire crire le code de) la classe Voiture
en dnissant ses getters et ses setters dans le chier Voiture.m. Je vous rappelle que
les getters vont permettre de lire le contenu des variables d'instance et que les setters
vont permettre de les modier.
Commenons par les getters. Le but du jeu est d'obtenir la valeur stocke dans les
82

DFINIR UNE CLASSE

variables d'instance modele et couleur. Une simple instruction return fera donc l'affaire :
1
2
3
4
5
6
7
8
9

# import " Voiture . h "


@implementation Voiture
- ( NSString *) modele {
return modele ;
}
- ( NSString *) couleur {
return couleur ;
}
@end

Passons maintenant aux setters. Leur but est de modier les valeurs contenues dans
les variables d'instance modele et couleur. Que pensez-vous du code suivant ?
1
2
3
4
5
6

- ( void ) setModele : ( NSString *) nouvModele {


modele = nouvModele ;
}
- ( void ) setCouleur : ( NSString *) nouvCouleur {
couleur = nouvCouleur ;
}

La version 4.2 de Xcode innove grandement en matire de gestion de la mmoire. Dans les versions prcdentes de Xcode, il tait ncessaire de dtruire
les variables lorsqu'elles n'taient plus utilises. Je dois avouer que vous avez
vraiment de la chance, car partir de maintenant, cette tape n'est plus
ncessaire et le code s'en trouve grandement simpli.

Vous devez encore crire une mthode pour dnir et initialiser les variables d'instance.
Cette mthode est le constructeur de la classe. Elle pourrait contenir quelque chose
comme ceci :
1
2
3
4
5
6
7
8
9

- ( id ) init
{
if ( self = [ super init ] )
{
[ self setModele : @ " Maserati Spyder " ];
[ self setCouleur : @ " Rouge " ];
}
return self ;
}

La premire ligne identie le constructeur. Ne cherchez pas comprendre le pourquoi


du comment : c'est la syntaxe utiliser !
En observant les lignes 5 et 6, vous pouvez dduire que ces deux instructions aectent
la valeur  Maserati Spyder  la variable d'instance modele en utilisant le setter
setModele et la valeur  Rouge  la variable d'instance couleur en utilisant le setter
83

CHAPITRE 6.

LA PROGRAMMATION ORIENTE OBJET

setCouleur.

Rien ne vous empche de choisir d'autres valeurs par dfaut, mais j'ai
pens que ce choix n'tait pas dpourvu d'intrt.
La troisime ligne aecte le rsultat de [super init] self.
Mais qu'est-ce que c'est que tout ce charabia ? Des explications s'il vous
plat !

Le mot self identie l'objet courant. Dans notre cas, une instance de la classe Voiture.
Quant au mot super, il identie la classe  parente , c'est--dire la classe partir de
laquelle la classe Voiture a t cre. Un simple coup d'il au chier Voiture.h nous
montre que la classe parente de Voiture est NSObject :
1
2
3

@interface Voiture : NSObject {


...
}

[super init] excute donc la mthode init de la classe parente. Ici, NSObject. Cette
mthode initialise la classe Voiture. La valeur renvoye est nil si un problme s'est
produit pendant l'initialisation. Dans le cas contraire, l'adresse de l'objet Voiture est
renvoye.

En thorie, cette adresse est identique celle qui se trouve dans self. Mais
il arrive quelques cas o cette adresse dire. En l'aectant l'objet self,
on est sr que self pointe sur l'objet Voiture.

L'instruction if teste la valeur stocke dans self, c'est--dire la valeur retourne


par [self init]. Si la valeur renvoye est dirente de nil, les variables d'instance
peuvent tre initialises. Dans le cas contraire, il est inutile de poursuivre l'excution
puisque l'initialisation de la classe a chou.
J'espre que l'initialisation de la classe n'a maintenant plus aucun secret pour vous.
N'hsitez pas relire plusieurs fois les lignes qui prcdent jusqu' ce que vous ayez bien
compris. Ne vous en faites toutefois pas si vous ne comprenez pas encore parfaitement
cette section. Cela viendra avec la pratique et vous n'en tes encore qu' vos premiers
pas en programmation Objective-C. Et croyez-moi, c'est assurment la partie la plus
dicile de votre apprentissage !
Allez, pour vous encourager, voici le code complet du chier Voiture.m :
1
2
3
4
5
6
7
8
9

84

# import " Voiture . h "


@implementation Voiture
- ( NSString *) modele {
return modele ;
}
- ( NSString *) couleur {
return couleur ;
}
- ( void ) setModele : ( NSString *) nouvModele

DFINIR DES MTHODES

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

modele = nouvModele ;
}
- ( void ) setCouleur : ( NSString *) nouvCouleur
{
couleur = nouvCouleur ;
}
- ( id ) init
{
if ( self = [ super init ] )
{
[ self setModele : @ " Ferrari 360 " ];
[ self setCouleur : @ " Rouge " ];
}
return self ;
}
@end

Copier ce code
Code web : 364854

Dnir des mthodes


Les mthodes Objective-C peuvent tre attaches une classe (mthode de classe) ou
une instance (mthode d'instance). Par exemple, stringWithFormat est une mthode
de classe, rattache la classe NSString ; ou encore arrayWithArray est une mthode
de classe, rattache la classe NSArray.
Dans une de vos applications, vous pourriez tre amens dnir une mthode d'instance nombreElementsTableau qui renverrait le nombre d'lments du tableau qui lui
est communiqu en paramtre. Voici la syntaxe gnrale permettant de dclarer une
mthode :
1
2
3
4

typeMethode ( typeRetour ) nomMethode : param tres


{
// Une ou plusieurs instructions
};

O :
 typeMethode vaut + pour une mthode de classe ou - pour une mthode d'instance ;
 typeRetour est le type de l'objet retourn par la mthode ;
 nomMethode est le nom de la mthode ;
 parametres correspond aux paramtres de la mthode, s'ils existent. Dans ce cas,
ils sont constitus d'un ou de plusieurs couples (type)nom, o type est le type du
paramtre et nom le nom du paramtre.
Quelques exemples vont vous aider y voir plus clair. L'instruction suivante dclare
la mthode d'instance premierJour, qui renvoie le nom du premier jour de la semaine
85

CHAPITRE 6.

LA PROGRAMMATION ORIENTE OBJET

lorsqu'on lui transmet une anne (an) et un numro de semaine (numSem) :


1

- ( NSString *) premierJour : ( int ) an : ( int ) numSem ;

Cette autre instruction dclare la mthode de classe maMethode, qui ne renvoie rien
(void) et qui ne demande aucun paramtre :
1

+ ( void ) maMethode ;

Enn, cette dernire instruction dclare la mthode d'instance changePropriete, qui


renvoie un boolen et qui admet deux paramtres : le nom de la proprit modier
(prop) et la valeur lui aecter (valeur) :
1

- ( BOOL ) changePropriete : ( NSString *) prop : ( NSString *) valeur ;

Ces dclarations de mthodes sont purement hypothtiques. Elles ont un


unique but : vous faire assimiler la syntaxe utiliser pour dnir des mthodes
d'instance et de classe, sans et avec paramtres. Vous tes certainement
impatients de mettre en pratique tout cela. Eh bien, c'est justement ce que
nous allons faire dans la section suivante.

Appeler des mthodes


Avant la pratique, un peu de thorie
En Objective-C, appeler une mthode de classe revient envoyer un message. Pour cela,
on utilise une syntaxe un peu particulire : le nom de l'objet est plac entre crochets
et on le fait suivre du nom de la mthode :
1

[ objet methode ];

Si la mthode demande une valeur en entre, faites suivre le nom de la mthode par le
caractre  :  et entrez la valeur aprs ce caractre :
1

[ objet methode : entree ];

Si une mthode demande plusieurs paramtres, sparez-les par un espace et indiquez


la valeur de ces paramtres aprs le caractre  : . Ici par exemple, trois paramtres
sont transmis la mthode. Le premier suit le nom de la mthode (methode:valeur1)
et les deux autres sont prcds du nom du paramtre correspondant (param2:valeur2
et param3:valeur3) :
1

[ objet methode : valeur1 param2 : valeur2 param3 : valeur3 ];

Une mthode peut retourner un objet. Dans ce cas, vous pouvez le stocker dans une
variable :
1

86

variable = [ objet methode ];

APPELER DES MTHODES

Ou encore :
1

variable = [ objet methode : entree ];

Si la mthode retourne un objet, vous pouvez enchaner plusieurs appels de mthodes


(c'est d'ailleurs ce qu'on appelle un chanage). Dans l'exemple suivant, le paramtre
param1 est envoy la mthode methode1, et cette dernire est applique l'objet
objet1. Le rsultat de la mthode est un objet auquel on applique la mthode methode2
avec le paramtre param2 :
1

[[ objet1 methode1 : param1 ] methode2 : param2 ];

Je vous conseille de limiter le chanage deux appels de mthodes. Au-del,


le code perd rapidement en lisibilit.

Si les choses ne sont pas trs claires, examinez la gure 6.7.

Figure 6.7  Le paramtre param1 est envoy la mthode methode1, et cette dernire

est applique l'objet objet1

Je ne comprends rien ce schma ! Pourrais-je avoir quelques explications ?

Pour comprendre ce schma, il sut de suivre les ches, de la gauche vers la droite.
parametre 1 est pass la methode 1 de l'objet 1. Cette mthode fait un traitement
et retourne un rsultat sous la forme d'un objet (la deuxime che rouge). La methode
2 de cet objet est excute, en lui passant le parametre 2 en entre (la troisime che
rouge). Le rsultat nal est reprsent par la quatrime che rouge. J'espre que c'est
plus clair cette fois-ci. Dans le cas contraire, relisez ce qui vient d'tre dit. Il n'y a rien
de vraiment sorcier l-dedans. . . ;-)
87

CHAPITRE 6.

LA PROGRAMMATION ORIENTE OBJET

Les mthodes ne sont pas l'apanage des objets : elles peuvent galement tre appliques
des classes. Par exemple, pour crer une variable de type NSString, vous appliquerez
la mthode string de la classe NSString :
1

NSString * uneChaine [ NSString string ];

Cette instruction peut tre simplie comme suit :


1

NSString * uneChaine ;

Je suis sr que vous prfrez la deuxime syntaxe la premire. Je dois bien avouer
que moi aussi !

Appel d'une mthode existante


Et maintenant, un peu de pratique. Vous allez utiliser un peu de code Objective-C
pour concatner (coller si vous prfrez) deux chanes NSString et acher le rsultat
dans la console du Simulateur iOS.
Dnissez un nouveau projet bas sur le modle Single View Application et donnezlui le nom  test . Cliquez sur ViewController.m dans le volet de navigation et reprez
la mthode viewDidLoad. Cette mthode est excute ds le dmarrage de l'application.
Vous allez y ajouter quelques instructions pour tester l'excution de mthodes. La
mthode viewDidLoad (ainsi que de nombreuses autres mthodes) a t gnre par
Xcode. Voici quoi elle doit ressembler :
1
2
3
4
5

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
// Do any additional setup after loading the view , typically
from a nib .
}

Le message [super viewDidLoad] excute la mthode viewDidLoad de la classe parente (super) de la classe en cours d'excution. tant donn que notre classe test
hrite de la classe UIView, cette instruction va excuter la mthode viewDidLoad de la
classe UIView.
Comme vous le verrez au fur et mesure de votre apprentissage, cette technique est des plus courantes. Juste pour vous en convaincre, examinez les
autres mthodes gnres par Xcode (viewDidUnoload, viewWillAppear,
viewDidAppear, etc.). Chacune d'elles utilise un message similaire.

La ligne de commentaire n'a aucune utilit. Vous pouvez la supprimer. Pour concatner deux chanes, vous utiliserez la mthode stringByAppendingString en envoyant
un message du type suivant : [chaine1 stringByAppendingString: chaine2]; o
chaine1 et chaine2 sont les deux chanes concatner.
Compltez la mthode viewDidLoad comme suit :
88

APPELER DES MTHODES

1
2
3
4
5
6
7

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
NSString * chaine = @ " un " ;
chaine = [ chaine stringByAppendingString : @ " texte " ];
NSLog ( @ " % @ " , chaine ) ;
}

Excutez l'application en cliquant sur l'icne Run. La gure 6.8 reprsente ce que vous
devriez obtenir dans la console.

Figure 6.8  Nos deux chanes ont bien t concatnes

Examinons les instructions utilises dans la mthode viewDidLoad.


La ligne 4 dnit l'objet NSString chaine et lui aecte la valeur  un  :
1

NSString * chaine = @ " un " ;

La ligne 5 applique la mthode stringByAppendingString l'objet NSString chaine


en lui passant le paramtre  texte . Le rsultat est stock dans l'objet chaine (chaine
=) :
1

chaine = [ chaine stringByAppendingString : @ " texte " ];

Enn, la ligne 6 ache le contenu de l'objet chaine (c'est--dire  un texte ) :


1

NSLog ( @ " % @ " , chaine ) ;

Cration et appel d'une mthode


Vous venez d'apprendre appeler la mthode stringByAppendingString. Cette mthode fait partie des mthodes standards de la classe NSString. Vous allez maintenant
aller un peu plus loin en crant une mthode et en l'appelant. Cette mthode :
1. aura pour nom  concat  ;
2. recevra deux paramtres NSString ;
3. renverra leur concatnation dans un objet NSString.
Munis de toutes ces informations, vous devriez pouvoir dnir le gabarit (c'est--dire
l'allure) de la mthode :
1

-( NSString *) concat :( NSString *) ch1 : ( NSString *) ch2 ;

89

CHAPITRE 6.

LA PROGRAMMATION ORIENTE OBJET

Cliquez sur ViewController.h dans le volet de navigation et ajoutez ce gabarit dans


le chier d'en-ttes, aprs l'instruction @interface.
Il n'y a rien de bien compliqu dans ce gabarit. Si vous ne comprenez pas comment
il est construit, relisez la section  Dnir des mthodes . Le chier d'en-ttes doit
maintenant ressembler ceci :
1
2
3
4
5
6

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
-( NSString *) concat :( NSString *) ch1 : ( NSString *) ch2 ;
@end

Maintenant, vous allez crire quelques lignes de code dans le chier ViewController.m.
Cliquez sur ce chier dans le volet de navigation et dnissez la mthode concat, juste
au-dessous de l'instruction @implementation :
1
2
3
4

-( NSString *) concat :( NSString *) ch1 : ( NSString *) ch2


{
return [ ch1 stringByAppendingString : ch2 ];
}

La premire ligne reprend le gabarit de la fonction.


La troisime ligne dnit l'objet retourn par la mthode (via return). Cet objet est
le rsultat de la concatnation de ch1 et ch2, passs en arguments.
Et maintenant, modiez la mthode viewDidLoad comme suit pour appeler la mthode
concat et acher le rsultat retourn dans la console :
1
2
3
4
5
6

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
NSString * chaine = [ self concat : @ " premier " : @ " deuxi me " ];
NSLog ( @ " % @ " , chaine ) ;
}

La ligne 4 dnit le NSString chaine (NSString* chaine) et lui aecte la valeur retourne par la mthode concat, en lui passant les NSString  premier  et  deuxime .
Que signie le mot self dans ce code ?

Il signie que la mthode concat a t dnie dans la classe courante, tout simplement.
Enn, la ligne 5 ache le rsultat retourn par concat dans la console. Excutez
l'application. La gure 6.9 reprsente ce que vous devriez obtenir dans la console.
90

APPELER DES MTHODES

Figure 6.9  Les deux chanes ont bien t concatnes

Crochet ou point ?
Deux styles d'criture peuvent tre utiliss pour appeler une mthode : les crochets ou
les points. titre d'exemple, les deux instructions suivantes sont quivalentes :
1
2

[ voiture setCouleur : @ " rouge " ];


voiture . couleur = @ " rouge " ;

Ces deux critures font une seule et mme action : elles appliquent la mthode couleur
l'objet voiture en lui passant l'entre rouge.
L'criture  point  ne fonctionne que pour les variables d'instance.

Les deux lignes suivantes sont elles aussi quivalentes :


1
2

laCouleur = [ voiture couleur ];


laCouleur = voiture . couleur ;

Vous l'aurez compris, elles lisent la couleur de l'objet voiture et la stockent dans la
variable laCouleur.

Crer un objet
La gestion mmoire d'un objet peut tre automatique ou manuelle. Dans le premier cas,
lorsque l'objet n'est plus utilis, il est automatiquement retir de la mmoire. Dans le
deuxime cas, c'est vous de le retirer de la mmoire pour viter qu'elle ne se sature.
titre d'exemple, pour crer l'objet NSString maChaine avec une gestion automatique
de la mmoire, vous utiliserez l'instruction suivante :
1

NSString * maChaine = [ NSString string ];

Ou plus simplement :
1

NSString * maChaine ;

Si vous prfrez grer manuellement l'objet


utiliserez l'instruction suivante :

NSString maChaine

en mmoire, vous
91

CHAPITRE 6.

LA PROGRAMMATION ORIENTE OBJET

NSString * maChaine = [[ NSString alloc ] init ];

Examinons cette deuxime criture. Dans un premier temps, la mthode alloc est
applique la classe NSString. Cette opration rserve un espace mmoire et instancie
un objet NSString. Dans un deuxime temps, la mthode init est applique cet
objet pour l'initialiser et le rendre utilisable (ce n'est qu'aprs l'initialisation de l'objet
que l'on peut lui appliquer des mthodes).
Si ncessaire, il est possible d'aecter une valeur un objet NSString.
Voici l'instruction utiliser si vous optez pour une gestion automatique de la mmoire :
1

NSString * maChaine = [ NSString stringWithString : @ " Une cha ne


quelconque " ];

Ou plus simplement :
1

NSString * maChaine = @ " Une cha ne quelconque " ;

Et voici les instructions utiliser si vous optez pour une gestion manuelle de la mmoire :
1
2

NSString * maChaine2 = [[ NSString alloc ] init ];


maChaine2 = @ " Une cha ne quelconque " ;

La gestion mmoire automatique ou manuelle ne se limite pas aux objets de


classe NSString : vous pouvez utiliser des techniques similaires pour crer et
instancier des objets d'une quelconque autre classe.

Cycle de vie des objets


Tout comme les tres vivants, les objets utiliss dans une application iOS ont un cycle
de vie.
1. Cration.
2. Utilisation.
3. Destruction.
Une trs bonne nouvelle : iOS 5 introduit un systme nomm ARC (Automatic Refequi automatise le cycle de vie des objets. Dsormais, c'est le compilateur qui se charge de cette tche ingrate qui consiste dtruire les objets une fois
qu'ils ne sont plus utiliss.
Je ne m'tendrai pas plus sur le sujet, mais sachez que vous chappez des complications aussi inutiles que dangereuses.
rence Counting )

92

APPELER DES MTHODES

En rsum
 En programmation oriente objet, les programmes sont constitus d'un ensemble de
blocs de code indpendants appels objets. Chaque objet contient sa propre boucle
d'attente. Lorsqu'un vnement concernant un objet particulier survient, c'est cet
objet de traiter l'vnement.
 Via l'instruction #import <UIKit/UIKit.h>, le chier .h fait rfrence au framework UIKit. Il dnit galement l'interface de l'application, les variables d'instance,
et leurs accesseurs (getters et setters).
 Le chier .m implmente les getters et les setters des objets utiliss dans l'application,
ainsi qu'une ou plusieurs mthodes complmentaires pour eectuer les traitements
demands par l'application.
 Les variables d'instance sont propres une instance de classe. Si plusieurs instances
sont excutes, les variables n'entreront donc pas en conit.
 Les mthodes sont appeles par l'intermdiaire de messages de type [objet methode];
ou [objet methode:entree];. Les mthodes peuvent tre chanes en imbriquant
plusieurs messages : [[objet1 methode1: param1] methode2: param2];.
 Pour appeler une mthode d'une variable d'instance, il est possible d'utiliser une
syntaxe  point . Ainsi, [objet methode] et objet.methode sont quivalents.
 Dans iOS 5, le systme ARC (Automatic Reference Counting ) automatise le cycle
de vie des objets : dsormais, c'est le compilateur qui se charge de dtruire les objets
une fois qu'ils ne sont plus utiliss.

93

CHAPITRE 6.

94

LA PROGRAMMATION ORIENTE OBJET

Chapitre

Les principaux objets utiliss en


Objective-C
Dicult :

n tant que programmeurs Objective-C, vous allez tre amens dialoguer avec des
mthodes de classes en leur envoyant des messages. Ce chapitre s'intresse aux classes
incontournables et aux mthodes qui vous seront les plus utiles.

95

CHAPITRE 7.

LES PRINCIPAUX OBJETS UTILISS EN OBJECTIVE-C

Chanes de caractres
Une chane de caractres est une suite de zro, un ou plusieurs caractres. Voici quelques
exemples de chanes de caractres :
Ceci est une cha ne de caract res
123 est plus petit que 456
@ / w &!

Dans une application destine aux iPhone, iPod Touch ou iPad, les chanes de caractres
sont manipules travers la classe Cocoa Touch NSString :
1

NSString * maChaine ;

Il se peut qu'un jour vous tombiez sur une variante de cette dclaration :
1
2
3

NSString * maChaine ;
( NSString *) maChaine ;
NSString * maChaine ;

Ces trois dclarations sont strictement quivalentes celle que je viens de vous prsenter.
Si ncessaire, il est possible d'aecter une valeur une chane lors de sa dnition :
1

NSString * maChaine = @ " Ceci est une cha ne de caract res " ;

Avez-vous remarqu le signe @ avant le dbut de la chane ? Il est l pour indiquer


Xcode que les caractres suivants sont une chane de caractres.
La classe NSString permet de dnir des chanes constantes, c'est--dire dont
le contenu ne varie pas. Si vous devez dnir des chanes dont le contenu et/ou
la taille peuvent changer, vous utiliserez plutt la classe NSMutableString.
Pour l'instant, la classe NSString sera bien susante. Vous en apprendrez
plus sur ces deux classes dans la suite de ce livre.

Et maintenant, nous allons voir comment manipuler les chanes de caractres en tudiant quelques mthodes de la classe NSString.

Tester l'galit de deux NSString


Il est souvent utile de comparer deux chanes entre elles. Vous pensez peut-tre qu'il
sut d'utiliser une instruction du type suivant :
1
2
3
4

96

if ( chaine1 == chaine2 )
{
// Traitement
}

CHANES DE CARACTRES

Eh bien, ce serait trop simple ! En fait, cette instruction compare non pas le contenu
mais l'adresse des deux chanes. Rappelez-vous, lorsque vous dnissez une nouvelle
chane, vous le faites en crant un pointeur :
1

NSString * chaine1 ;

Heureusement, il existe une solution pour comparer simplement deux chanes. Vous
utiliserez pour cela la mthode isEqualToString de la classe NSString :
1
2
3
4

if ([ chaine1 isEqualToString : chaine2 ])


{
// Traitement
}

Si cette syntaxe vous laisse perplexes, jetez un il la section  Appeler des mthodes 
du chapitre prcdent (page 86) et tout deviendra plus clair. Pour ceux qui auraient la
mmoire courte, les mthodes de classe sont appeles en utilisant la syntaxe suivante :
1

[ objet methode : entr e ];

Dans le cas qui nous occupe, la mthode isEqualToString est applique l'objet
chaine1 en lui transmettant l'objet chaine2 en entre. Cette mthode retourne la
valeur TRUE si les deux chanes sont gales, FALSE dans le cas contraire.

Longueur d'un NSString


La longueur d'une chane est obtenue avec la mthode length de la classe NSString.
Voici un exemple d'utilisation de cette mthode :
1
2

NSString * a = @ " ceci est une cha ne " ;


NSLog ( @ " Longueur de la chaine : % i " , [ a length ]) ;

L'instruction NSLog ache le texte suivant dans le volet de dbogage :


Longueur de la cha ne : 19

Notez que les espaces sont comptes. Eh oui, ce sont aussi des caractres.

Concatner deux NSString


Pour concatner deux chanes, c'est--dire pour les mettre bout bout, vous utiliserez
la mthode stringWithFormat :
1
2
3

NSString * chaine1 = @ " premi re partie " ;


NSString * chaine2 = @ " deuxi me partie " ;
NSString * chaine3 ;

97

CHAPITRE 7.

LES PRINCIPAUX OBJETS UTILISS EN OBJECTIVE-C

chaine3 = [ NSString stringWithFormat : @ " % @ %@ " , chaine1 , chaine2 ];


NSLog ( @ " % @ " , chaine3 ) ;

4
5

Les trois premires instructions ne devraient pas vous poser de problme. Pour tous
ceux qui pensent que la quatrime ligne est incomprhensible, faisons quelques tapes
intermdiaires. L'objet NSString chaine3 a t dni la ligne prcdente. Pour lui
aecter une valeur, il sut de faire suivre son nom du signe = et de la valeur souhaite :
chaine3 = valeur;.
La valeur est obtenue en utilisant la mthode stringWithFormat de la classe NSString.
Le dbut de l'expression est donc tout fait clair : [NSString stringWithFormat
...].
La mthode stringWithFormat admet un paramtre de type NSString. Dans cet
exemple, ce paramtre a pour valeur @"%@%@",chaine1,chaine2. Le signe @ devant
le premier guillemet indique que la suite est une chane de caractres. Quant aux %@, ils
se rfrent aux lments spcis juste aprs le deuxime guillemet. Ainsi, le premier
%@ est remplac par chaine1 et le deuxime par chaine2. Le rsultat renvoy est la
concatnation des deux chanes. L'instruction NSLog ache donc le texte suivant dans
le volet de dbogage :
premi re partie deuxi me partie

Dnir une chane pendant l'excution d'une l'application


Supposons que l'objet
suivante :
1

NSString maChaine

soit dni et initialis avec l'instruction

NSString * maChaine = @ " Bonjour " ;

Pour initialiser un objet NSString partir d'une chane de type char, vous utiliserez
les instructions suivantes :
1
2
3
4
5
6

char * chaineC ;
NSString * chaineObjC ;
...
// Instructions qui initialisent la variable char chaineC
...
chaineObjC = [ NSString stringWithString : chaineC ];

Inversement, pour initialiser une chane de type char partir d'un objet NSString,
vous utiliserez les instructions suivantes :
1
2
3

98

const char * chaineC ;


NSString * chaineObjC = @ " Bonjour " ;
chaineC = [ chaineObjC String ];

NOMBRES

Parcourir un NSString, caractre par caractre


Un jour ou l'autre, vous serez certainement confronts ce problme : comment isoler
chacun des caractres contenus dans un objet NSString an d'eectuer des comparaisons ou de leur appliquer un traitement individuel ? La solution est des plus simples :
il sut d'appliquer de manire rptitive la mthode characterAtIndex la chane.
1
2
3
4
5
6
7
8
9
10

NSString * chaine ;
chaine = @ " helloworld " ;
int i = chaine . length ; // La variable i contient le nombre de
caract res de la cha ne
int j ;
char uneLettre ;
for ( j = 0; j < i ; j ++) // Boucle de 0 i en incr mentant j
{
uneLettre = [ chaine characterAtIndex : j ]; // Extraction d 'un
caract re de la cha ne
NSLog ( @ " La lettre en position % i est % c " , j , uneLettre ) ;
}

La gure 7.1 reprsente le rsultat dans la fenter de dbogage.

Figure 7.1  Le rsultat s'ache dans la fentre de dbogage

Nombres
Nous allons ici parler des objets de classe NSNumber, qui peuvent laisser perplexe. En
eet, pourquoi utiliser une classe ddie la manipulation des nombres alors que les
types int, float, double, etc. sont dj disponibles ?
Et pourtant, vous aurez besoin de la classe NSNumber dans plusieurs cas bien prcis.
Par exemple, pour convertir des types de donnes. Le type d'un objet NSNumber peut
tre facilement modi en utilisant les mthodes floatValue, doubleValue, intValue,
longValue, etc. Ici par exemple, un nombre entier est converti en un nombre double
avec la mthode doubleValue :
99

CHAPITRE 7.

LES PRINCIPAUX OBJETS UTILISS EN OBJECTIVE-C

NSNumber * unEntier = [ NSNumber numberWithInteger : 23 ];


float unDouble = [ unEntier doubleValue ];

1
2

La premire instruction dnit l'objet unEntier de type NSNumber et l'initialise avec la


valeur entire 23. La deuxime instruction dnit la variable unDouble de type float
et lui aecte la conversion en un double de l'objet unEntier.
la vue de ce code, vous vous sentez certainement dsorients. Ne vous en faites pas,
tout deviendra plus clair au fur et mesure de votre apprentissage. Pour l'instant, il
vous sut de savoir que les types numriques cohabitent avec la classe NSNumber, et
que cette dernire est utile dans certains cas bien prcis.

Dates et heures
Plusieurs classes sont associes la manipulation des objets date et heure dans ObjectiveC : NSDate, NSCalendar, NSTimeZone, NSDateComponents, NSDateFormatter. Pour
mieux apprhender ces direntes classes, rien de tel qu'un peu de code.

Achage de la date courante


Ces quelques lignes de code achent la date courante au format amricain (en_US) et
franais (fr_FR) :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

/* ---D finition de l ' objet date et de sa mise en forme - - - */


// Aujourd ' hui
NSDate * date = [ NSDate date ];
NSDateFormatter * miseEnForme = [[ NSDateFormatter alloc ] init ];
// Aucun affichage de l ' heure
[ miseEnForme setTimeStyle : NSDateFormatterNoStyle ];
// Affichage de la date au format semi - abr g
[ miseEnForme setDateStyle : NSDateFormatterMediumStyle ];
/* --- Affichage de la date au format US - - - */
NSLocale * usLocale = [[ NSLocale alloc ] initWithLocaleIdentifier
: @ " en_US " ];
[ miseEnForme setLocale : usLocale ];
NSLog ( @ " Date au format % @ : % @ " , [[ miseEnForme locale ]
localeIdentifier ] , [ miseEnForme stringFromDate : date ]) ;
/* --- Affichage de la date au format FR - - - */
NSLocale * frLocale = [[ NSLocale alloc ] initWithLocaleIdentifier
: @ " fr_FR " ];
[ miseEnForme setLocale : frLocale ];
NSLog ( @ " Date au format % @ : % @ " , [[ miseEnForme locale ]
localeIdentifier ] , [ miseEnForme stringFromDate : date ]) ;

100

DATES ET HEURES

Copier ce code
B
Code web : 534925


Et voici ce que a donne dans la console :
[...] test [1527:207] Date au format en_US : Jun 7 , 2011
[...] test [1527:207] Date for locale fr_FR : 7 juin 2011

Cette syntaxe est vraiment incroyable et j'ai peur d'tre dpass ! Est-ce que
j'aurais rat un chapitre ?

Examinons le premier bloc d'instructions. La ligne 4 dnit l'objet NSDate


et lui aecte la date courante ([NSDate date]).

*date)
1

date (NSDate

NSDate * date = [ NSDate date ];

La ligne 5 dnit l'objet miseEnForme de type NSDateFormatter. C'est par l'intermdiaire de cet objet que l'on dnira un format d'achage pour la date.
1

NSDateFormatter * miseEnForme = [[ NSDateFormatter alloc ] init ];

La ligne 8 indique que l'heure ne doit pas tre ache. La mthode setTimeStyle est
donc applique l'objet miseEnForme en lui transmettant un paramtre :
1

[ miseEnForme setTimeStyle : NSDateFormatterNoStyle ];

Enn, la quatrime instruction donne le format d'achage de la date. Les messages


autoriss pour la mthode setDateStyle sont :
 NSDateFormatterNoStyle
 NSDateFormatterShortStyle
 NSDateFormatterMediumStyle
 NSDateFormatterLongStyle
 NSDateFormatterFullStyle
Je vous invite modier l'instruction en question an d'observer les dirents comportements de ces mthodes.
1

[ miseEnForme setDateStyle : NSDateFormatterMediumStyle ];

Examinons maintenant le deuxime bloc d'instructions. La ligne 14 dnit l'objet


NSLocale usLocale et l'initialise au format en_US, c'est--dire anglais amricain :
1

NSLocale * usLocale = [[ NSLocale alloc ] initWithLocaleIdentifier


: @ " en_US " ];

La ligne suivante utilise la classe setLocale pour indiquer l'objet NSDateFormatter


miseEnForme que l'achage devra se faire au format anglais amricain :
1

[ miseEnForme setLocale : usLocale ];

101

CHAPITRE 7.

LES PRINCIPAUX OBJETS UTILISS EN OBJECTIVE-C

Enn, la ligne 16 ache la date courante dans ce format. Le premier message entre
crochets rcupre l'identicateur de langue (en_US) et le deuxime la date au format
miseEnForme :
NSLog ( @ " Date au format % @ : % @ " , [[ miseEnForme locale ]
localeIdentifier ] , [ miseEnForme stringFromDate : date ]) ;

Le troisime bloc d'instructions est trs proche du deuxime, ceci prs qu'il demande
l'achage de la date au format franais.

Cration d'une date relative la date systme


La mthode initWithTimeIntervalSinceNow permet de crer un objet NSDate en lui
appliquant un dcalage par rapport la date systme. Le dcalage peut tre positif
(pour dnir une date postrieure la date systme) ou ngatif (pour dnir une date
antrieure la date systme). Examinez le code suivant :
NSDate * dateCourante = [ NSDate date ]; // Aujourd ' hui
NSTimeInterval secondesParJour = 24 * 60 * 60 ;
NSDate * demain = [[ NSDate alloc ] initWithTimeIntervalSinceNow :
secondesParJour ];
NSDate * hier = [[ NSDate alloc ] initWithTimeIntervalSinceNow : secondesParJour ];

1
2
3
4

La premire ligne dnit l'objet NSDate dateCourante et y mmorise la date systme. La deuxime ligne dnit l'objet NSTimeInterval secondesParJour et y mmorise le nombre de secondes contenues dans une journe. La troisime ligne dnit
l'objet NSDate demain et y stocke la date systme plus un jour. Pour cela, la mthode initWithTimeIntervalSinceNow lui est applique en lui transmettant la valeur
secondesParJour. L'objet demain est donc initialis avec la date qui suit le jour courant. La quatrime ligne est trs proche de la troisime, mais ici, le paramtre pass
la mthode initWithTimeIntervalSinceNow est gal -secondesParJour. L'objet
hier est donc initialis avec la date qui prcde le jour courant.

Dnition d'une date autre que la date systme


Pour dnir une date dirente de la date systme, vous devez :
1. dnir et initialiser un objet NSDateComponents ;
2. l'aecter un objet NSDate via un objet NSCalendar.
Tout ceci a l'air bien compliqu, mais vous allez voir qu'il n'en est rien en examinant
le code suivant :
1
2
3

// D finition d 'un objet NSDateComponents


NSDateComponents * nsDatePerso = [[ NSDateComponents alloc ] init
];
[ nsDatePerso setYear : 2065 ];

102

DATES ET HEURES

4
5
6
7
8
9

[ nsDatePerso setMonth : 8 ];
[ nsDatePerso setDay : 12 ];
// Cr ation d ' un objet NSDate et affectation de l ' objet
nsDatePerso d fini pr c demment
NSDate * datePerso = [[ NSCalendar currentCalendar ]
dateFromComponents : nsDatePerso ];
NSLog ( @ " Date utilisateur : % @ " , datePerso ) ;

Voici le rsultat ach dans la console :


[...] test [1680:207] Date utilisateur : 2065 -08 -11 22:00:00
+0000

Comme vous le voyez, aucune mise en forme NSFormatter n'a t applique l'objet
datePerso.
Examinons les instructions qui composent ce code. La premire instruction dnit
l'objet NSDateComponents nsDatePerso et rserve son emplacement en mmoire :
1

NSDateComponents * nsDatePerso = [[ NSDateComponents alloc ] init


];

Les trois instructions suivantes initialisent les composants anne, mois et jour de cet
objet.
1
2
3

[ nsDatePerso setYear : 2065 ];


[ nsDatePerso setMonth : 8 ];
[ nsDatePerso setDay : 12 ];

Le deuxime bloc d'instructions dnit un objet NSDate de nom datePerso (NSDate


*datePerso). Cet objet est initialis avec la date dnie dans l'objet nsDatePerso
(dateFromComponents:nsDatePerso) en passant par un objet NSCalendar ([NSCalendar
currentCalendar]) :
1

NSDate * datePerso = [[ NSCalendar currentCalendar ]


dateFromComponents : nsDatePerso ];

Une variante pour dnir une date autre que la date systme
Pour dnir et initialiser un objet NSDate avec une date dirente de la date systme, il est galement possible d'utiliser une chane de caractres. Cette technique
est plus simple que la prcdente. Elle consiste passer en paramtre la chane qui
contient la date la mthode dateFromString, qui elle-mme est applique un objet
NSDateFormatter :
1
2
3

NSDateFormatter * df = [[ NSDateFormatter alloc ] init ];


[ df setDateFormat : @ " dd - MM - yyyy " ];
NSDate * uneDate = [ df dateFromString : @ " 12 - 08 - 2011 " ];

103

CHAPITRE 7.

LES PRINCIPAUX OBJETS UTILISS EN OBJECTIVE-C

La premire instruction dnit l'objet NSDateFormatter


ment en mmoire :

df et lui rserve un emplace-

NSDateFormatter * df = [[ NSDateFormatter alloc ] init ];

La deuxime instruction dnit le format utilis dans l'objet NSDateFormatter :


1

[ df setDateFormat : @ " dd - MM - yyyy " ];

Enn, la troisime instruction aecte une date l'objet NSDate uneDate en transmettant une chane la mthode dateFromString de l'objet NSDateFormlatter df :
NSDate * uneDate = [ df dateFromString : @ " 12 - 08 - 2011 " ];

Extraction des composants d'un objet NSDate


Pour accder aux composants (jour, mois, anne, heure, minute et seconde) d'une date
au format NSDate, vous devez utiliser la mthode components: fromDate: d'un objet
NSCalendar dans lequel vous aurez stock la date.
titre d'exemple, le code ci-dessous extrait le jour, le mois, l'anne, l'heure, les minutes
et les secondes de la date systme et les ache dans la console :
NSDate * date = [ NSDate date ]; // Aujourd ' hui
NSCalendar * calendrier = [ NSCalendar currentCalendar ];
NSDateComponents * composants = [ calendrier components :(
NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit
| NSHourCalendarUnit | NSMinuteCalendarUnit |
NSSecondCalendarUnit ) fromDate : date ];
NSLog ( @ " Nous sommes le % i / % i / % i " , [ composants day ] , [
composants month ] , [ composants year ]) ;
NSLog ( @ " Il est % i : % i : % i " , [ composants hour ] , [ composants
minute ] , [ composants second ]) ;

1
2
3

4
5

Copier ce code
B
Code web : 977790


La premire instruction cre l'objet NSDate
1

date

NSDate * date = [ NSDate date ]; // Aujourd ' hui

La deuxime instruction cre l'objet NSCalendar


1

et y stocke la date systme :


calendrier

NSCalendar * calendrier = [ NSCalendar currentCalendar ];

La troisime instruction cre l'objet NSDateComponents


composants suivants de l'objet NSDate date :
 anne : NSYearCalendarUnit
 mois : NSMonthCalendarUnit
 jour : NSDayCalendarUnit
 heure : NSHourCalendarUnit
104

composants

et lui aecte les

DATES ET HEURES

 minutes : NSMinuteCalendarUnit
 secondes : NSSecondCalendarUnit
Les deux dernires instructions achent les composants de la date systme dans la
console, ce qui donne le rsultat suivant :
[...] test [1897:207] Nous sommes le 7 / 6 / 2011
[...] test [1897:207] Il est 16 : 39 : 6

Ajouter ou soustraire des dates


Pour ajouter ou soustraire un certain nombre d'annes, de mois et de jours une date,
vous devez crer un objet dateComponents, y stocker la valeur ajouter ou soustraire
et ensuite utiliser la mthode dateByAddingComponents:toDate pour ajuster la date
d'origine. titre d'exemple, nous allons ajouter 1 an, 3 mois et 10 jours la date
systme et acher le rsultat dans la console. Voici le code utilis :
1
2
3
4
5
6
7
8
9
10

NSDate * date = [ NSDate date ]; // Aujourd ' hui


NSDateComponents * leGap = [[ NSDateComponents alloc ] init ];
[ leGap setYear : 1 ];
[ leGap setMonth : 3 ];
[ leGap setDay : 10 ];
NSDate * nouvelleDate = [[ NSCalendar currentCalendar ]
dateByAddingComponents : leGap toDate : date options : 0 ];
NSLog ( @ " Date syst me : % @ " , date ) ;
NSLog ( @ " Nouvelle date : % @" , nouvelleDate ) ;

La date systme puis la nouvelle date sont aches dans la console :


[...] test [1995:207] Date syst me : 2011 -06 -07 14:59:53 +0000
[...] test [1995:207] Nouvelle date : 2012 -09 -17 14:59:53 +0000

Examinons les instructions utilises. La premire ligne dnit l'objet NSDate


y stocke la date systme :
1

et

NSDate * date = [ NSDate date ];

La deuxime ligne dnit l'objet NSDateComponents


en mmoire :
1

date

leGap et rserve son emplacement

NSDateComponents * leGap = [[ NSDateComponents alloc ] init ];

Les trois lignes suivantes initialisent le dcalage souhait dans l'objet leGap :
1
2
3

[ leGap setYear : 1 ];
[ leGap setMonth : 3 ];
[ leGap setDay : 10 ];

105

CHAPITRE 7.

LES PRINCIPAUX OBJETS UTILISS EN OBJECTIVE-C

La nouvelle date est calcule dans l'objet NSDate nouvelleDate. Les composants dnis dans l'objet leGap sont ajouts (dateByAddingComponents:leGap) l'objet NSDate
date (toDate: date) :
NSDate * nouvelleDate = [[ NSCalendar currentCalendar ]
dateByAddingComponents : leGap toDate : date options : 0 ];

Calculer la dirence entre deux dates


Il est parfois ncessaire de calculer la dirence entre deux dates. En Objective-C, cela
se fait en appliquant les mthodes fromDate et toDate un objet NSCalendar. Voici
le code :
1
2
3
4
5
6
7
8
9

NSDateFormatter * df = [[ NSDateFormatter alloc ] init ];


[ df setDateFormat : @ " yyyy - MM - dd " ];
NSDate * dateA = [ NSDate date ]; // Aujourd ' hui
NSDate * dateB = [ df dateFromString :@ " 2011 - 01 - 01 " ];
NSCalendarUnit calendrier = NSYearCalendarUnit |
NSMonthCalendarUnit | NSDayCalendarUnit ;
NSDateComponents * difference = [[ NSCalendar currentCalendar ]
components : calendrier fromDate : dateA toDate : dateB options : 0
];
NSInteger mois = [ difference month ];
NSInteger jours = [ difference day ];
NSLog ( @ " Diff rence entre les deux dates : %i mois et % i jours . "
, mois , jours ) ;

Copier ce code
B
Code web : 791255


Examinons ce code. Les deux premires instructions dnissent et initialisent l'objet
NSDateFormatter df :
1
2

NSDateFormatter * df = [[ NSDateFormatter alloc ] init ];


[ df setDateFormat : @ " yyyy - MM - dd " ];

Les deux instructions suivantes stockent la date courante ainsi qu'une autre date (celle
du 01/01/2011) dans les objets NSDate dateA et dateB :
1
2

NSDate * dateA = [ NSDate date ]; // Aujourd ' hui


NSDate * dateB = [ df dateFromString :@ " 2011 - 01 - 01 " ];

L'instruction suivante dnit les composants qui seront utiliss pour calculer la dirence entre les deux dates (ici les annes, les mois et les jours) :
1

NSCalendarUnit calendrier = NSYearCalendarUnit |


NSMonthCalendarUnit | NSDayCalendarUnit ;

L'instruction suivante calcule la dirence entre les deux dates. L'instruction est assez consquente, alors prenez le temps de bien la comprendre. Dans la section  Extraction des composants d'un objet NSDate , vous avez appris utiliser la mthode
106

DATES ET HEURES

pour extraire les composants (anne, mois, jour, heures, minutes, . . .) d'une date. Ici, nous allons utiliser la mthode components: fromDate:
toDate: pour eectuer une soustraction entre deux dates et en extraire les composants.
Dans un premier temps, un objet NSCalendar est obtenu avec le message [NSCalendar
currentCalendar].
La mthode components: fromDate: toDate: est alors excute. La dirence entre
les dates dateA et dateB est calcule (fromDate:dateA toDate:dateB), et seuls les
composants dnis dans l'objet NSCalendatUnit calendrier sont retourns. Le rsultat est stock dans l'objet NSDateComponents difference :
components: fromDate

NSDateComponents * difference = [[ NSCalendar currentCalendar ]


components : calendrier fromDate : dateA toDate : dateB options : 0
];

Il ne reste plus qu' extraire les composants ans, mois et jour du rsultat et les
stocker dans des objets NSInteger :
1
2
3

NSInteger ans = [ difference year ];


NSInteger mois = [ difference month ];
NSInteger jours = [ difference day ];

Il ne reste plus qu' les acher dans la console :


1

NSLog ( @ " Diff rence entre les deux dates : % ans % i mois et % i
jours . " , ans , mois , jours ) ;

Temps ncessaire pour excuter un bloc d'instructions


Pendant la mise au point d'une application, il peut tre utile de calculer le temps
ncessaire l'excution d'un bloc de code. Voici comment procder :
1. dnissez un objet NSDate et initialisez-le avec la date courante juste avant le
bloc de code dont vous voulez tester le temps d'excution ;
2. excutez le bloc de code ;
3. appliquez la mthode timeIntervalSinceNow l'objet NSDate initialis l'tape
1 et mmorisez le rsultat dans un objet NSTimeInterval.
Voici un exemple de code qui teste le temps ncessaire l'achage de 100 lignes dans
la console :
1
2
3
4
5
6
7

NSDate * debut = [ NSDate date ]; // Date courante


// On affiche 100 lignes dans la console gr ce une boucle
int compteur ;
for ( compteur = 1 ; compteur < 100 ; compteur ++)
{
NSLog ( @ " abc " ) ;

107

CHAPITRE 7.

8
9
10

LES PRINCIPAUX OBJETS UTILISS EN OBJECTIVE-C

11

NSTimeInterval intervalle = [ debut timeIntervalSinceNow ]; // On


calcule le temps d ' ex cution ...
NSLog ( @ " Temps coul : % f " , intervalle ) ; // Et on l ' affiche

La gure 7.2 reprsente les dernires informations aches dans la console.

Figure 7.2  On calcul le temps que prennent 100 lignes s'acher dans la console

Tableaux
La classe NSArray est ddie la manipulation de tableaux (un tableau est un assemblage d'objets quelconques : c'est une faon de les ranger, comme dans une armoire).
En programmation, on parle aussi d'array (d'o le nom de la classe NSArray).
Les tableaux Objective-C sont de taille xe, mais vous pouvez cependant les
rallouer pour obtenir un nombre d'lments dirent.

Dnir et initialiser un tableau


Pour crer un tableau contenant une chane de caractres, vous utiliserez l'instruction
suivante :
1

NSArray * monTableau = [ NSArray arrayWithObject : @ " premier " ];

Pour crer un tableau contenant un entier, vous utiliserez l'instruction suivante :


1

NSArray * monTableau = [ NSArray arrayWithObject :[ NSNumber


numberWithInt : 10 ]];

Pour crer un tableau contenant plusieurs chanes de caractres, vous utiliserez l'instruction suivante :
108

TABLEAUX

NSArray * monTableau = [ NSArray arrayWithObjects : @ " premier " ,@ "


deuxi me " ,@ " troisi me " ,@ " quatri me " , nil ];

Le dernier lment du tableau doit avoir pour valeur nil.

Enn, pour crer un tableau partir d'un autre tableau, vous utiliserez l'instruction
suivante :
1

NSArray * monTableau2 = [ NSArray arrayWithArray : monTableau1 ];

Accder aux objets contenus dans un tableau


Plusieurs mthodes trs pratiques permettent d'accder aux informations contenues
dans un objet NSArray.
 containsObject renvoie la valeur true si le tableau contient au moins un objet. Il
renvoie la valeur false dans le cas contraire.
 count retourne le nombre d'objets du tableau.
 objectAtIndex retourne l'objet situ l'index (c'est--dire la position) spci
dans le tableau.
 lastObject retourne le dernier objet contenu dans le tableau, c'est--dire celui dont
l'index est le plus lev.
Par convention, le premier lment d'un tableau Objective-C se trouve la
position 0. On dit que son index est 0. Le deuxime lment se trouve la
position 1. Son index est 1. Ainsi de suite jusqu'au dernier lment.

Pour clarier ces mthodes, rien de tel que quelques exemples :


1
2
3
4
5
6
7
8
9
10
11
12
13
14

NSArray * monTableau = [ NSArray arrayWithObjects : @ " premier " ,@ "


deuxi me " ,@ " troisi me " ,@ " quatri me " , nil ];
NSLog ( @ " % @ " , monTableau ) ;
NSLog ( @ " Objet qui se trouve l ' index 1 : % @ " , [ monTableau
objectAtIndex : 1 ]) ;
if ([ monTableau containsObject : @ " premier " ])
NSLog ( @ " L ' objet premier a t trouv dans le tableau " ) ;
else
NSLog ( @ " L ' objet premier n 'a pas t trouv dans le tableau " ) ;
if ([ monTableau containsObject : @ " dixi me " ])
NSLog ( @ " L ' objet dixi me a t trouv dans le tableau " ) ;
else
NSLog ( @ " L ' objet dixi me n 'a pas t trouv dans le tableau " ) ;

109

CHAPITRE 7.

LES PRINCIPAUX OBJETS UTILISS EN OBJECTIVE-C

NSLog ( @ " Dernier objet du tableau : % @ " , [ monTableau lastObject


]) ;

15

Examinons ces instructions. La premire ligne dnit l'objet NSArray monTableau


et l'initialise avec quatre chanes de caractres : premier, deuxime, troisime et
quatrime :
NSArray * monTableau = [ NSArray arrayWithObjects : @ " premier " ,@ "
deuxi me " ,@ " troisi me " ,@ " quatri me " , nil ];

La deuxime instruction (NSLog(@"%@",monTableau);) ache le contenu du tableau


dans la console.
La troisime instruction ache l'objet qui se trouve en position 1 (le deuxime donc,
puisque l'index commence 0) :
NSLog ( @ " Objet qui se trouve l ' index 1 : % @ " , [ monTableau
objectAtIndex : 1 ]) ;

Et voici les informations retournes dans la console :


[...] test [1095:207] Objet qui se trouve l ' index 1 : deuxi me

Le premier bloc if else utilise la mthode containsObject pour tester la prsence


de l'objet premier dans le tableau et ache un message en consquence :
1
2
3
4

if ([ monTableau containsObject : @ " premier " ])


NSLog ( @ " L ' objet premier a t trouv dans le tableau " ) ;
else
NSLog ( @ " L ' objet premier n 'a pas t trouv dans le tableau " ) ;

Ici, l'objet premier faisant partie du tableau, voici ce qu'ache la console :


[...] test [1095:207] L ' objet premier a t trouv dans le
tableau

Le bloc if else suivant utilise la mthode containsObject pour tester la prsence de


l'objet dixime dans le tableau et acher un message en consquence :
1
2
3
4

if ([ monTableau containsObject : @ " dixi me " ])


NSLog ( @ " L ' objet dixi me a t trouv dans le tableau " ) ;
else
NSLog ( @ " L ' objet dixi me n 'a pas t trouv dans le tableau " ) ;

L'objet dixime ne faisant pas partie du tableau, voici ce qu'ache la console :


[...] test [1095:207] L ' objet dixi me n ' a pas t trouv dans le
tableau

Enn, la dernire instruction ache le dernier objet du tableau :


1

110

NSLog ( @ " Dernier objet du tableau : % @ " , [ monTableau lastObject


]) ;

TABLEAUX

Comme prvu, le dernier objet est la chane quatrime :


[...] test [1095:207] Dernier objet du tableau : quatri me

Passer en revue les objets contenus dans un tableau


Vous vous en doutez certainement, la lecture successive des dirents objets contenus
dans un tableau se fera dans une boucle. Les objets peuvent tre retrouvs avec la
mthode objectAtIndex ou avec la mthode objectEnumerator. Nous allons examiner
tour tour ces deux possibilits.
Avec la mthode objectAtIndex
1
2
3
4
5
6

NSArray * monTableau = [ NSArray arrayWithObjects : @ " premier " ,@ "


deuxi me " ,@ " troisi me " ,@ " quatri me " , nil ];
int nombreElements = [ monTableau count ];
for ( int i = 0 ; i < nombreElements ; i ++)
{
NSLog ( @ " Objet de rang % i : % @ " , i , [ monTableau objectAtIndex :
i ]) ;
}

La premire instruction dnit l'objet NSArray monTableau et y stocke quatre chanes


de caractres. Je ne vous remets pas le code, ce stade vous devriez avoir compris.
La deuxime instruction dnit l'entier nombreElements et y stocke le nombre d'lments du tableau :
1

int nombreElements = [ monTableau count ];

La boucle
d'objets :
1

for

excute l'instruction

NSLog()

autant de fois que le tableau contient

for ( int i = 0 ; i < nombreElements ; i ++)

L'instruction NSLog de la ligne 5 accde aux lments du tableau en passant l'index de


la boucle la mthode objectAtIndex et en l'appliquant l'objet monTableau :
1

NSLog ( @ " Objet de rang % i : % @ " , i , [ monTableau objectAtIndex : i


]) ;

Le rsultat ach dans la console est bien celui qu'on attendait :


[...]
[...]
[...]
[...]

test2 [1417:207]
test2 [1417:207]
test2 [1417:207]
test2 [1417:207]

Objet
Objet
Objet
Objet

de
de
de
de

rang
rang
rang
rang

0
1
2
3

:
:
:
:

premier
deuxi me
troisi me
quatri me

Avec la mthode objectEnumerator

111

CHAPITRE 7.

1
2
3
4
5
6
7

LES PRINCIPAUX OBJETS UTILISS EN OBJECTIVE-C

NSArray * monTableau = [ NSArray arrayWithObjects : @ " premier " ,@ "


deuxi me " ,@ " troisi me " ,@ " quatri me " , nil ];
NSEnumerator * enumer = [ monTableau objectEnumerator ];
NSObject * obj ;
while (( obj = [ enumer nextObject ]) != nil )
{
NSLog ( @ " Objet : % @ " , obj ) ;
}

La premire instruction dnit l'objet NSArray monTableau et y stocke quatre chanes


de caractres.
La deuxime instruction cre l'objet enumer de type NSEnumerator et l'initialise avec
un numrateur bas sur l'objet monTableau :
1

NSEnumerator * enumer = [ monTableau objectEnumerator ];

Ce type d'objet permet de dcrire trs facilement des tableaux. Pour en savoir plus sur
ce sujet, consultez l'aide en cliquant sur les mots NSEnumerator (1) et objectEnumerator
(2), et si ncessaire en activant les icnes Hide or show the Utilities (3) et Show
Quick Help (4), comme indiqu la gure 7.3.

Figure 7.3  Consultez l'aide

L'instruction suivante dnit l'objet obj de type NSObject :


1

112

NSObject * obj ;

DICTIONNAIRES

En appliquant la mthode nextObject l'objet NSEnumerator enumer, on obtient


tour tour tous les objets stocks dans le tableau monTableau. Lorsque tout le tableau
a t parcouru, la mthode nextObject renvoie la valeur nil. La faon la plus simple
de passer en revue tout le contenu du tableau consiste utiliser une boucle while :
1

while (( obj = [ enumer nextObject ]) != nil )

Si l'objet renvoy par la mthode nextObject est dirent de nil, il est ach dans
la console :
1

NSLog ( @ " Objet : % @ " , obj ) ;

Dans le cas contraire, la boucle while prend n. Voici le rsultat ach dans la console :
[...]
[...]
[...]
[...]

test2 [1507:207]
test2 [1507:207]
test2 [1507:207]
test2 [1507:207]

Objet
Objet
Objet
Objet

:
:
:
:

premier
deuxi me
troisi me
quatri me

Il existe un deuxime type de tableau en Objective-C : le NSMutableArray.


Comme son nom le laisse supposer, il permet de manipuler des tableaux
de taille variable. Si cela vous intresse, consultez la documentation ofcielle. En particulier, voyez comment utiliser les mthodes addObject:,
insertObject:atIndex: et removeObjectAtIndex: qui permettent respectivement d'ajouter un objet la n du tableau, d'ajouter un objet une
position de votre choix et de supprimer un objet.

B

Lire la documentation
Code web : 505214

Dictionnaires
Parfois, l'ordre dans lequel sont mmoriss les lments importe peu. Ce qui importe
plutt, c'est d'associer chacun des objets mmoriss un autre objet unique. Par
exemple, il pourrait tre intressant de dnir des couples nom/dnition, ou encore
nom/adresse. Les dnitions ou adresses pourraient alors tre retrouves en fournissant
le nom correspondant.
Les classes NSDictionary et NSMutableDictionary rpondent parfaitement cette
problmatique. Vous utiliserez un dictionnaire NSDictionary lorsque les objets mmoriser sont immuables, c'est--dire lorsqu'ils ne sont pas modis aprs leur cration
et leur initialisation. Par contre, vous utiliserez un dictionnaire NSMutableDictionary
lorsque les objets mmoriser peuvent tre modis aprs leur cration et leur initialisation.
113

CHAPITRE 7.

LES PRINCIPAUX OBJETS UTILISS EN OBJECTIVE-C

Cration et initialisation d'un dictionnaire


Voici les instructions utiliser :
NSDictionary * leDictionnaire = [ NSDictionary dictionary ];
NSMutableDictionary * leDictionnaire = [ NSMutableDictionary
dictionary ];

1
2

Pour ajouter des lments dans un dictionnaire, vous appliquerez la mthode setObject
l'objet NSDictionary ou NSMutableDictionary en lui transmettant le couple de valeurs mmoriser :
1
2

[ leDictionnaire setObject : @ " une d finition " forKey : @ " une cl


d ' acc s " ];
[ leDictionnaire setObject : @ " une autre d finition " forKey : @ "
une autre cl d ' acc s " ];

Si vous le souhaitez, la mthode dictionaryWithObjectsAndKeys permet de regrouper


la dnition et l'initialisation d'un dictionnaire dans une seule instruction :
1

NSDictionary * leDictionnaire = [ NSDictionary


dictionaryWithObjectsAndKeys : @ " Une d finition " , @ " une cl " ,
@ " Une autre d finition " , @ " une autre cl " , nil ];

Comme vous pouvez le voir, les objets stocks dans le dictionnaire sont spars entre
eux par des virgules et la valeur nil identie la n du dictionnaire.
Enn, sachez qu'un dictionnaire peut tre cr partir de deux NSArray. Le premier
doit contenir les objets stocker (dnitions ou adresses), le deuxime les cls associes
(noms) :
1
2
3

NSArray * lesObjets = [ NSArray arrayWithObjects : @ " une d


finition " , @ " une autre d finition " , nil ];
NSArray * lesCles = [ NSArray arrayWithObjects : @ " une cl " , @ " une
autre cl " , nil ];
NSDictionary * leDictionnaire = [[ NSDictionary alloc ]
initWithObjects : lesObjets forKeys : lesCles ];

Mthodes relatives aux dictionnaires


Pour connatre le nombre d'entres stockes dans un dictionnaire, il sut d'appliquer
la mthode count l'objet dictionnaire :
1

NSLog ( @ " Nombre d ' entr es m moris es dans le dictionnaire = % i "


, [ leDictionnaire count ]) ;

Pour obtenir l'objet qui correspond une cl donne, vous utiliserez la mthode
objectForKey :
1

114

NSLog ( @ " La cl ' une cl ' correspond la cha ne = '% @ '" , [


leDictionnaire objectForKey : @ " une cl d ' acc s " ]) ;

DICTIONNAIRES

Enn, vous pouvez utiliser les mthodes removeObjectForKey et removeAllObjects


pour supprimer, respectivement, l'entre dont la cl est spcie ou toutes les entres
du dictionnaire :
1
2

[ leDictionnaire removeObjectForKey : @ " une cl " ];


[ leDictionnaire removeAllObjects ];

Un exemple de code
Ce petit exemple de code comment illustre les instructions dont nous venons de parler :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

// On cr e un dictionnaire
NSMutableDictionary * leDictionnaire = [ NSMutableDictionary
dictionary ];
// On remplit le dictionnaire avec des couples adresse / nom
[ leDictionnaire setObject : @ " 12 rue Gu rin 75013 Paris " forKey :
@ " Pierre Jaquart " ];
[ leDictionnaire setObject : @ " 26 rue de la Place 75002 Paris "
forKey : @ " Eric Courteau " ];
[ leDictionnaire setObject : @ " 115 rue des p cheurs 75005 Paris "
forKey : @ " Jean Bertier " ];
[ leDictionnaire setObject : @ "2 place Mayeur 75012 Paris " forKey
: @ " Placido Perez " ];
// On affiche le nombre d ' entr es du dictionnaire
NSLog ( @ " Nombre d ' entr es m moris es dans le dictionnaire : % i "
, [ leDictionnaire count ]) ;
// On affiche une des entr es du dictionnaire
NSLog ( @ " Le nom ' Eric Courteau ' correspond l ' adresse '% @ '" , [
leDictionnaire objectForKey : @ " Eric Courteau " ]) ;
// On supprime une entr e du dictionnaire
[ leDictionnaire removeObjectForKey : @ " Jean Bertier " ];
// On affiche le nombre d ' entr es du dictionnaire , apr s la
suppression d ' une des entr es
NSLog ( @ " Nombre d ' entr es m moris es dans le dictionnaire : % i "
, [ leDictionnaire count ]) ;

Copier ce code
Code web : 533412


Et voici ce qu'ache la console :
B

[...] test [2996: f803 ] Nombre d ' entr es m moris es dans le


dictionnaire : 4
[...] test [2996: f803 ] Le nom ' Eric Courteau ' correspond l '
adresse '26 rue de la Place 75002 Paris '

115

CHAPITRE 7.

LES PRINCIPAUX OBJETS UTILISS EN OBJECTIVE-C

[...] test [2996: f803 ] Nombre d ' entr es m moris es dans le


dictionnaire : 3

Ensembles
Dans les sections prcdentes, vous avez fait connaissance avec les tableaux et les
dictionnaires. Les tableaux permettent de stocker des objets dans un certain ordre. Ces
derniers peuvent alors tre retrouvs par leur index. Les dictionnaires dnissent des
couples valeurs/cls. Les valeurs sont retrouves en spciant les cls correspondantes.
Il existe une troisime faon de stocker des objets : en utilisant des ensembles, via la
classe NSSet, vous pouvez mmoriser un empilement d'objets sans ordre particulier.

Cration et initialisation d'un ensemble


Pour crer un ensemble qui contient un seul objet :
NSSet * monEnsemble = [ NSSet setWithObject :[ NSNumber
numberWithInt : 2 ]];

Pour crer un ensemble partir d'un tableau :


NSSet * monEnsemble = [ NSSet setWithArray : monTableau ];

Pour crer un ensemble qui contient plusieurs objets :


NSSet * monEnsemble = [[ NSSet alloc ] initWithObjects : @ " un " ,@ "
deux " ,@ " trois " , nil ];

Mthodes relatives aux ensembles


Recherche d'un objet dans un ensemble

La mthode containsObject permet de savoir si un objet fait partie d'un ensemble.


Si l'objet est trouv, la valeur true est renvoye par la mthode. Dans le cas contraire,
c'est la valeur false qui est renvoye. Ici, l'objet deux est recherch dans l'ensemble
monEnsemble. Un texte est ach dans la console s'il est trouv :
1
2
3
4

if ([ monEnsemble containsObject : @ " deux " ])


{
NSLog ( @ " La cha ne deux a t trouv e dans l ' ensemble " ) ;
}

116

ENSEMBLES

Rcupration d'un objet dans un ensemble

Pour rcuprer un objet dans un ensemble, vous utiliserez la mthode member. Si l'objet
est prsent, il est renvoy par la mthode. Dans le cas contraire, c'est la valeur nil qui
est renvoye. Ici, l'objet deux est recherch dans l'ensemble monEnsemble. S'il existe,
il est ach dans la console :
1
2
3
4
5

id unMembre = [ monEnsemble member :( @ " deux " ) ];


if ( unMembre != nil )
{
NSLog ( @ " Objet % @ " , unMembre ) ;
}

Rcupration des objets d'un ensemble

La mthode allObjects permet de rcuprer tous les objets d'un ensemble sous la
forme d'un NSArray :
1

NSArray * leTableau = [ monEnsemble allObjects ];

La mthode
semble :
1

objectEnumerator

permet de rcuprer un

NSEnumerator

sur un en-

NSEnumerator * enumer = [ monEnsemble objectEnumerator ];

Enn, la mthode anyObject permet de rcuprer un objet quelconque d'un ensemble :


1

id unObjetQuelconque = [ monEnsemble anyObject ];

En rsum
 Les chanes de caractres sont manipules travers la classe NSString. Pour dnir
une chane, utilisez l'instruction NSString *maChaine.
 int, float, double, etc. ne sont pas les seuls types de donnes numriques. Vous
pouvez aussi utiliser des objets de classe NSNumber dans certains cas particuliers, par
exemple pour eectuer des conversions de donnes.
 Les classes NSDate, NSCalendar, NSTimeZone, NSDateComponents et NSDateFormatter
permettent de manipuler des objets date et heure. Vous pouvez dnir une date en
rapport (ou non) avec la date systme, extraire les composantes d'un objet NSDate,
ajouter ou soustraire des dates, calculer la dirence entre deux dates, etc.
 La classe NSArray est ddie la manipulation de tableaux. Lorsqu'un tableau a t
dni, vous pouvez tester son contenu avec la mthode containsObject, et accder
aux objets qui le composent avec les mthodes objectAtIndex et objectEnumerator.
 Les classes NSDictionary et NSMutableDictionary permettent de dnir des dictionnaires. Pour initialiser un dictionnaire, vous utiliserez les mthodes setObject,
dictionnaryWithObjectAndKeys et initWithObjects.
117

CHAPITRE 7.

LES PRINCIPAUX OBJETS UTILISS EN OBJECTIVE-C

 Pour mmoriser des objets en les empilant, vous utiliserez un ensemble. Lorsqu'un
ensemble a t dni, vous pouvez tester si un objet en fait partie, rcuprer un objet
donn, un objet quelconque, tous les objets ou un numrateur.

118

Chapitre

TP : Un jeu de Mastermind
Dicult :

ous voici donc arrivs au premier TP ! TP signie  Travaux Pratiques . En clair,


vous allez pratiquer ce que nous venons de voir. Rgulirement, je vous ferai travailler
grce ce genre d'exercices et vous allez vite voir que, mine de rien, vous en savez
des choses.
videmment, je ne vous demanderai jamais rien que vous ne soyez capables de faire. Enn
pas vraiment. . . Il se peut que cela arrive, mais dans ce cas je vous donnerai la marche
suivre pour parvenir la n du TP. Bon, vous tes prts ? Alors allons-y !

119

CHAPITRE 8.

TP : UN JEU DE MASTERMIND

Instructions pour raliser le TP


Dans ce premier programme, votre device va choisir un nombre de quatre chires au
hasard. Vous devrez le trouver en un minimum d'essais en proposant des nombres de
quatre chires. Pour chaque proposition, le nombre de chires bien placs sera indiqu.
Le rsultat attendu se trouve la gure 8.1.

Figure 8.1  Le rendu attendu de notre Mastermind

Pour parvenir ce rsultat, vous devrez :


1. dnir une application base sur le modle Single View Application ;
2. crer l'interface de l'application dans Interface Builder ;
3. relier les lments de l'interface au code Objective-C ;
4. tirer au hasard un nombre de quatre chires ;
5. acher le clavier lorsque le joueur clique dans la zone de saisie et l'eacer lorsqu'il
valide sa saisie en appuyant sur Retour ;
6. crire les instructions ncessaires pour comparer les nombres proposs par le
joueur et le nombre dcouvrir et acher un message en consquence.
Normalement, seule l'tape 4 devrait vous poser un problme. Les autres ont dj t
vues ; si vous avez le moindre problme avec, n'hsitez pas lire les chapitres prcdents
correspondants.
Pour tirer un nombre alatoire, nous utiliserons la fonction arc4random(), qui renvoie
un nombre alatoire compris entre 0 et 4 294 967 295. Sauf que nous voulons un nombre
120

CORRECTION

de 4 chires, donc compris entre 1000 et 9999. Bref, on en est loin. Nous allons donc
devoir ruser, grce au modulo. Regardez le code suivant :
1

arc4random () % 9000 + 1000 ;

arc4random() % 9000 renvoie un nombre compris


1000, le nombre est compris entre 1000 et 9999.

entre 0 et 8999. En lui ajoutant

L'achage du clavier est automatique lorsque le joueur clique dans la zone de saisie.
Par contre, ce sera vous de faire disparatre le clavier lorsque le joueur validera la
saisie en appuyant sur la touche Retour. Cette action sera accomplie en appelant la
mthode resignFirstResponder de la classe sender.
Je suis sr que vous tes presss de commencer. Imaginez un peu, votre premire
application ! Alors, n'attendez plus, commencez ds maintenant. Et soyez assurs que
je ne serai pas loin de vous. Si vous avez une dicult quelconque, reportez-vous la
correction qui suit. J'ai dtaill chaque tape de faon ce qu'aucun blocage ne vous
empche d'arriver au bout du TP. Cependant, il est tout fait normal de passer un
long moment rchir ce que vous devez faire. Vous pouvez mme vous aider d'une
feuille blanche et d'un stylo en mettant par crit vos ides.

Correction
J'espre que vous n'avez pas eu trop de problmes dans ce TP. Voici ma correction,
dans laquelle je passe en revue tous les points qui auraient pu  coincer .

Cration de l'application
Dans Xcode, slectionnez Create a new Xcode project dans la bote de dialogue
ache au lancement du programme. Si aucune bote de dialogue n'est ache, lancez
la commande New/New project dans le menu File. Dans la bote de dialogue Choose a
template for your new project, choisissez Single View Application puis cliquez
sur Next. Donnez le nom mastermind l'application, tapez test dans la zone de texte
Company Identifier, cochez la case Use Storyboard et cliquez sur Next. Choisissez
un dossier pour stocker l'application et validez en cliquant sur Create. Au bout de
quelques instants, le squelette de l'application est cr.

Dnition de l'interface
Sous le dossier mastermind, cliquez sur l'entre mainStoryboard.storyboard dans la
barre de navigation (volet gauche de l'application). Une interface dsesprment vide
est ache dans la partie droite de la fentre (gure 8.2). Rassurez-vous, nous allons
trs vite la remplir.
Dans la partie suprieure droite de la fentre (c'est--dire dans la barre d'outils), audessus du libell View, cliquez sur l'icne Hide or Show the utilities (1) et cliquez
121

CHAPITRE 8.

TP : UN JEU DE MASTERMIND

Figure 8.2  L'interface est vide

sur l'icne Show the Object


indiqu la gure 8.3.

Library (2) pour faire apparatre la bibliothque, comme

Figure 8.3  Il faut acher la librairie d'objets

Ajoutez deux Label, un Text Field, un Text View et un Round Rect Button l'interface, puis redimensionnez-les pour obtenir une disposition semblable la gure 8.4.
122

CORRECTION

Figure 8.4  Disposition des objets de l'application

123

CHAPITRE 8.

TP : UN JEU DE MASTERMIND

Double-cliquez tour tour sur les dirents contrles et insrez le texte spci dans
le tableau suivant :
Contrle

Premier Label
Deuxime Label
Text View
Round Rect
Button

Texte

Saurez-vous trouver le nombre de quatre chires que j'ai


choisi ?
Tentez votre chance
Choisir un autre nombre

Pour mettre
 n et valider la saisie d'un texte dans un contrle, appuyez sur
la touche Entre du clavier.
Le texte saisi dans le premier
deux lignes ?

Label

est trop long. Comment l'acher sur

Si ncessaire, cliquez sur l'icne Show the Attributes inspector dans la partie suprieure du volet gauche. Si vous cliquez sur le Label, ses caractristiques apparaissent
dans le volet de l'inspecteur, comme sur la gure 8.5. Slectionnez Word Wrap dans la
liste droulante Line Breaks, tapez 2 dans la zone de texte Lines et redimensionnez
le contrle pour obtenir l'eet recherch.

Figure 8.5  Il faut acher le texte sur deux lignes

Pour supprimer le texte propos par dfaut dans le contrle TextView, cliquez dessus
dans Interface Builder,slectionnez
le texte dans la zone Text du volet de l'inspecteur,

appuyez sur la touche Suppr 
, puis sur la touche Entre du clavier.
8.6
124

CORRECTION

Figure 8.6  Suppression du texte par dfaut

125

CHAPITRE 8.

TP : UN JEU DE MASTERMIND

Pour faciliter la saisie dans le Text Field, vous pouvez demander l'achage d'un clavier numrique : cliquez sur l'icne Show the Attributes
inspector dans la barre d'outils et aectez la valeur Numbers and
Punctuation au paramtre Keyboard, comme indiqu la gure 8.7. Ainsi,
le clavier ach pour la saisie ne contiendra que des chires et des signes.

Figure 8.7  Pour acher un clavier numrique

Liaison des contrles au code


Cachez la zone d'utilitaires en cliquant sur l'icne Hide or show the Utilities (1)
et achez le code ViewController.h en cliquant sur l'icne Show the Assistant
editor (2), comme montr la gure 8.8.
Si la zone de navigation prend trop de place sur le ct gauche de la fentre,
vous pouvez la cacher en cliquant sur l'icne Hide or show the Navigator
(dans la partie droite de la barre d'outils, au-dessus du libell View).

Vous allez maintenant relier les contrles de l'interface au code.


Contrle-glissez-dposez tour tour les contrles Text Field et Text View de l'interface jusqu'au volet de code. Donnez le nom saisie au Text Field, et le nom
resultats au Text View.
126

CORRECTION

Figure 8.8  Il est temps d'acher le code de l'application

Si vous avez suivi mes indications, le chier ViewController.h doit maintenant ressembler ceci :
1
2
3
4
5
6
7

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
@property ( weak , nonatomic ) IBOutlet UITextField * saisie ;
@property ( weak , nonatomic ) IBOutlet UITextView * resultats ;
@end

Pour terminer les liaisons, vous devez dnir une action pour le contrle Round Rect
Button. Contrle-glissez-dposez ce contrle juste avant l'instruction @end. Au relchement du bouton gauche de la souris, slectionnez Action dans la zone Connection,
tapez autrenombre dans la zone de texte Name et cliquez sur Connect (gure 8.9).

Figure 8.9  Dnition d'une action pour le contrle Round

Rect Button

127

CHAPITRE 8.

TP : UN JEU DE MASTERMIND

La ligne suivante est ajoute au code :


1

- ( IBAction ) autrenombre :( id ) sender ;

Sauvegardez votre projet avec la commande Save dans le menu File. Juste histoire de
souer un peu, vous pouvez cliquer sur l'icne Run dans la barre d'outils et savourer
votre travail. Le rsultat ach devrait tre semblable la gure 8.10.

Figure 8.10  Voici quoi ressemble l'application pour le moment

Cliquez sur Stop pour revenir la dure ralit : vous devez maintenant crire le code
qui donnera vie l'application !
Avant de commencer, cliquez sur ViewController.h dans le volet de navigation et
dnissez la variable d'instance nombreChoisi de type int pour mmoriser le nombre
choisi par le device. Le chier d'en-ttes doit maintenant ressembler ceci :
1
2
3
4
5
6
7
8
9
10

@interface ViewController : UIViewController


{
int nombreChoisi ;
}
@property ( weak , nonatomic ) IBOutlet UITextField * saisie ;
@property ( weak , nonatomic ) IBOutlet UITextView * resultats ;
- ( IBAction ) autrenombre :( id ) sender ;
@end

128

CORRECTION

Je vous sens vraiment impatients de faire fonctionner l'application. Alors, passons sans
plus attendre l'criture du code.

criture du code
Si ncessaire, achez la zone de navigation en cliquant sur l'icne Hide or show the
Navigator, dans la partie droite de la barre d'outils, au-dessus du libell View. Cliquez sur mastermindViewController.m dans la zone de navigation. Le code gnr
par Xcode est de taille respectable. Il contient les direntes mthodes utilises par
l'application :
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

// Pour une meilleure lisibilit , j 'ai supprim les commentaires


ajout s automatiquement au d but du fichier par Xcode
# import " ViewController . h "
@implementation ViewController
@synthesize saisie ;
@synthesize resultats ;
- ( void ) didReceiveMemoryWarning
{
[ super didReceiveMemoryWarning ];
// Release any cached data , images , etc that aren 't in use .
}
# pragma mark - View lifecycle
- ( void ) viewDidLoad
{
[ super viewDidLoad ];
// Do any additional setup after loading the view , typically
from a nib .
}
- ( void ) viewDidUnload
{
[ self setSaisie : nil ];
[ self setResultats : nil ];
[ super viewDidUnload ];
// Release any retained subviews of the main view .
// e . g . self . myOutlet = nil ;
}
- ( void ) viewWillAppear :( BOOL ) animated
{
[ super viewWillAppear : animated ];
}

129

CHAPITRE 8.

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

TP : UN JEU DE MASTERMIND

- ( 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 ) ;
}
- ( IBAction ) autrenombre :( id ) sender {
}
@end

En examinant les dernires lignes, vous reconnaissez certainement la partie dclarative


lie l'action sur le contrle Round Rect Button :
1
2

- ( IBAction ) autrenombre :( id ) sender {


}

Quelques lignes plus haut, la mthode


l'application :
1
2
3
4
5

viewDidLoad

va vous permettre d'initialiser

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
// Do any additional setup after loading the view , typically
from a nib .
}

Mais pourquoi serait-il ncessaire d'initialiser l'application me direz-vous ? Eh bien. . .


pour choisir le nombre dcouvrir !
Tirage alatoire du nombre dcouvrir

Ajoutez la ligne que nous avons vue plus haut, aprs [super
1

130

nombreChoisi = arc4random () % 9000 + 1000 ;

viewDidLoad];

CORRECTION

L'application sait maintenant tirer au hasard un nombre compris entre 1000 et 9999.
Traitement suite la proposition d'un nombre

Lorsque le joueur a saisi un nombre de quatre chires, il appuie sur la touche Return
pour valider la saisie. Le clavier doit alors disparatre de l'cran et le nombre entr
doit tre compar au nombre dcouvrir. Pour ce faire, il est ncessaire de capturer
l'vnement  appui sur la touche Return  et de le relier une mthode an d'eectuer
les traitements ncessaires. Dans un premier temps, commencez par dnir la mthode
saisieReturn dans le chier d'en-ttes. Cliquez sur ViewController.h dans le volet
de navigation et entrez cette ligne, juste au-dessus du @end nal :
1

- ( IBAction ) saisieReturn :( id ) sender ;

Le chier d'en-ttes doit maintenant ressembler ceci :


1
2
3
4
5
6
7
8
9
10
11
12
13

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
{
int nombreChoisi ;
}
@property ( weak , nonatomic ) IBOutlet UITextField * saisie ;
@property ( weak , nonatomic ) IBOutlet UITextView * resultats ;
- ( IBAction ) autrenombre :( id ) sender ;
- ( IBAction ) saisieReturn :( id ) sender ;
@end

Pour crire le code qui eace le clavier de l'cran, cliquez sur ViewController.m dans
le volet de navigation et dnissez la mthode saisieReturn comme suit :
1
2
3
4

-( IBAction ) saisieReturn :( id ) sender


{
[ sender resignFirstResponder ];
}

La mthode resignFirstResponder eace le clavier. C'est aussi simple que cela !


N'essayez pas d'excuter l'application : vous devez auparavant relier l'vnement  appui sur la touche Retour  la mthode saisieReturn.
Pour cela, slectionnez l'entre MainStoryboard.storyboard dans la zone de navigation, achez le volet des utilitaires en cliquant sur Hide or show the Utilities
dans la barre d'outils, puis cliquez sur Show the Connections inspector, dans la
partie suprieure. Cliquez sur le contrle Text Field dans la zone d'dition pour le
slectionner. Sous Sent Events, reprez le rond droite de l'vnement Did End On
Exit et dplacez-le sur l'icne View Controller, dans la partie infrieure de la zone
d'dition. Au relchement du bouton gauche de la souris, deux choix vous sont proposs : autreNombre et saisieReturn (gure 8.11). Cliquez sur saisieReturn. Ainsi,
131

CHAPITRE 8.

TP : UN JEU DE MASTERMIND

la mthode saisieReturn sera excute lorsque l'utilisateur appuiera sur la touche


Return du tlphone.

Figure 8.11  Deux choix sont proposs : autreNombre et saisieReturn

Vous pouvez maintenant excuter l'application et vrier que l'appui sur la touche
Return dissimule le clavier.
Il est temps maintenant d'crire le code relatif au traitement du nombre choisi par
le joueur. Cliquez sur ViewController.m dans la zone de navigation et compltez la
mthode saisieReturn comme suit :
1
2
3
4
5
6
7
8
9

-( IBAction ) saisieReturn :( id ) sender


{
[ sender resignFirstResponder ];
int bienPlace = 0 ;
int charIndex ; // Index de boucle pour parcourir tous les
caract res des cha nes comparer
unichar testChar1 , testChar2 ; // Les caract res comparer :
testChar1 dans le nombre propos , testChar2 dans le nombre
trouver
for ( charIndex = 0 ; charIndex < 4 ; charIndex ++)
{
testChar1 = [ saisie . text characterAtIndex : charIndex ];

132

CORRECTION

testChar2 = [[ NSString stringWithFormat : @ " % d " , nombreChoisi


] characterAtIndex : charIndex ];
if ( testChar1 == testChar2 )
bienPlace ++;

10
11
12
13
14
15
16
17

}
resultats . text = [ NSString stringWithFormat : @ " % @ % @% d % @ % @ " ,
saisie . text , @ " : Bien plac s : " , bienPlace , @ " \ r" ,
resultats . text ];
if ( bienPlace == 4 )
resultats . text = [ NSString stringWithFormat : @ " % @ % d" , @ "
Bravo , le r sultat tait " , nombreChoisi ];

Examinons un peu ce code ensemble.


Comme il a t dit prcdemment, la ligne 3 supprime le clavier de l'cran. Jusque-l,
tout va bien !
Le bloc d'instructions suivant (lignes 4 13) compare le nombre entr par le joueur au
nombre dcouvrir. Les premires lignes dclarent plusieurs variables :
 la variable entire bienPlace est dnie et initialise 0 : int bienPlace = 0;
 la variable entire charIndex est dnie mais non initialise : int charIndex;
 il en va de mme pour les variables unichar testChar1 et testChar2 : unichar
testChar1, testChar2;

La comparaison des quatre chires se fait dans une boucle for, en utilisant la variable
comme index de boucle :

charIndex
1

for ( charIndex = 0 ; charIndex < 4 ; charIndex ++)

l'intrieur de la boucle, la premire instruction s'intresse la saisie du joueur. Elle


isole le caractre d'index charIndex et le stocke dans la variable unichar testChar1 :
1

testChar1 = [ saisie . text characterAtIndex : charIndex ];

La deuxime instruction fait de mme, mais sur le nombre tir alatoirement. L'instruction est plus complexe, car le nombre choisi alatoirement est un int et non un
NSString. Il est donc ncessaire de le convertir en NSString avant de procder l'extraction :
1

testChar2 = [[ NSString stringWithFormat : @ " % d " , nombreChoisi ]


characterAtIndex : charIndex ];

Le premier message convertit l'int


1

nombreChoisi

en un NSString :

[ NSString stringWithFormat : @ " % d" , nombreChoisi ]

On extrait de l'objet ainsi obtenu le caractre qui se trouve l'emplacement charIndex


(characterAtIndex:charIndex) et on mmorise ce caractre dans la variable testChar2
(testChar2 =).
Il ne reste plus qu' comparer testChar1 testChar2 et incrmenter la variable
bienPlace si ces deux variables sont gales :
133

CHAPITRE 8.

1
2

TP : UN JEU DE MASTERMIND

if ( testChar1 == testChar2 )
bienPlace ++;

Une fois que les quatre chires ont t tests, il faut acher le rsultat dans le contrle
TextView. C'est le rle de l'instruction suivante :
resultats . text = [ NSString stringWithFormat : @ " % @ %@ % d % @ % @ " ,
saisie . text , @ " : Bien plac s : " , bienPlace , @ " \r " ,
resultats . text ];

On utilise pour cela une chane formate ([NSString


minons le format de la chane ache :
1

stringWithFormat: ...]). Exa-

%@%@%d%@%@

En comptant le nombre de %, vous pouvez facilement dduire que cette chane est
compose de cinq lments. De gauche droite, deux chanes (%@), un nombre dcimal
(%d) et deux chanes (%@). Ces lments sont les suivants :
 la valeur saisie par le joueur, saisie.text ;
 le texte  Bien placs :  ;
 la valeur dcimale bienPlace, convertie en une chane de caractres ;
 un saut de ligne \r ;
 les direntes informations prcdemment aches dans le contrle TextView.
La dernire instruction teste si la partie est termine :
1
2

if ( bienPlace == 4 )
resultats . text = [ NSString stringWithFormat : @ " % @ %d " , @ " Bravo ,
le r sultat tait " , nombreChoisi ];

Si le nombre de caractres bien placs est gal 4 (if (bienPlace == 4)), cela signie
que le nombre entr est gal au nombre dcouvrir. Dans ce cas, un message est ach
dans le contrle TextView resultats (resultats.text =). Ici encore, nous utilisons
une chane formate ([NSString stringWithFormat: ...]). Comme vous pouvez le
voir, le texte ach est compos d'une chane et d'un nombre entier : le texte  Bravo,
le rsultat tait , suivi du nombre dcouvrir.
Tirage alatoire d'un autre nombre

Pour terminer ce programme, il reste crire le code relatif l'appui sur le bouton
Choisir un autre nombre. Rassurez-vous, cette tche vous paratra on ne peut plus
simple aprs ce que vous venez de vivre ! L'entre ViewController.m tant slectionne
dans le volet de navigation, dplacez-vous dans la partie infrieure du code et compltez
la mthode autrenombre comme suit :
1
2
3
4
5

- ( IBAction ) autrenombre :( id ) sender


{
nombreChoisi = arc4random () % 9000 + 1000 ;
resultats . text = [ NSString stringWithFormat : @ " % @ " , @ " J 'ai
choisi un nouveau nombre \ r " ];
}

134

CORRECTION

La premire instruction est identique celle qui a dj t utilise pour tirer un nombre
alatoire. Elle choisit un nombre compris entre 1000 et 9999 et le stocke dans la composante text de l'objet label nombreChoisi :
1

nombreChoisi = arc4random () % 9000 + 1000 ;

La deuxime instruction ache le message  J'ai choisi un nouveau nombre  dans le


contrle TextView :
1

resultats . text = [ NSString stringWithFormat : @ " \% @ " , @ " J 'ai


choisi un nouveau nombre \ textbackslash {} r " ];

L'application est entirement fonctionnelle. Cliquez sur Run et amusez-vous bien !

Le code complet
Je vous mets ici le code complet de l'application, que vous pouvez copier grce au code
web suivant.

Copier
le
code
B
Code web : 503914


ViewController.h
1
2
3
4
5
6
7
8
9
10
11
12
13

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
{
int nombreChoisi ;
}
@property ( weak , nonatomic ) IBOutlet UITextField * saisie ;
@property ( weak , nonatomic ) IBOutlet UITextView * resultats ;
- ( IBAction ) autrenombre :( id ) sender ;
- ( IBAction ) saisieReturn :( id ) sender ;
@end

ViewController.m
1
2
3
4
5
6
7
8
9

# import " ViewController . h "


@implementation ViewController
@synthesize saisie ;
@synthesize resultats ;
- ( void ) didReceiveMemoryWarning
{
[ super didReceiveMemoryWarning ];

135

CHAPITRE 8.

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

TP : UN JEU DE MASTERMIND

// Release any cached data , images , etc that aren 't in use .

# pragma mark - View lifecycle


- ( void ) viewDidLoad
{
[ super viewDidLoad ];
nombreChoisi = arc4random () % 9000 + 1000 ;
}
- ( void ) viewDidUnload
{
[ self setSaisie : nil ];
[ self setResultats : 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 ) ;
}
- ( IBAction ) autrenombre :( id ) sender
{

136

CORRECTION

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

nombreChoisi = arc4random () % 9000 + 1000 ;


resultats . text = [ NSString stringWithFormat : @ " % @ " , @ " J ' ai
choisi un nouveau nombre \ r " ];

-( IBAction ) saisieReturn :( id ) sender


{
[ sender resignFirstResponder ];
int bienPlace = 0 ;
int charIndex ;
unichar testChar1 , testChar2 ;
for ( charIndex = 0 ; charIndex < 4 ; charIndex ++)
{
testChar1 = [ saisie . text characterAtIndex : charIndex ];
testChar2 = [[ NSString stringWithFormat : @ " % d " , nombreChoisi
] characterAtIndex : charIndex ];
if ( testChar1 == testChar2 )
bienPlace ++;
}
resultats . text = [ NSString stringWithFormat : @ " % @ % @% d % @ % @ " ,
saisie . text , @ " : Bien plac s : " , bienPlace , @ " \ r" ,
resultats . text ];
if ( bienPlace == 4 )
resultats . text = [ NSString stringWithFormat : @ " % @ % d" , @ "
Bravo , le r sultat tait " , nombreChoisi ];
}
@end

137

CHAPITRE 8.

138

TP : UN JEU DE MASTERMIND

Troisime partie
Cration d'interfaces graphiques

139

Chapitre

Fentres, vues et contrles


Dicult :

es iPhone, iPad et iPod Touch ont une particularit : ils ne sont capables d'acher
qu'une seule fentre sur l'cran. Ceci les direncie des ordinateurs, sur lesquels un
nombre indni de fentres peut tre ach.
Pour que cette spcicit ne soit pas une limitation, les devices iOS peuvent acher plusieurs vues et les  empiler  selon les directives du programmeur.
Une vue est constitue d'un ou de plusieurs contrles. Il peut s'agir d'informations (textes,
images, vidos), d'lments pour communiquer avec l'utilisateur (boutons, zones de texte,
curseurs, etc.) ou encore d'lments pour basculer entre les direntes vues (onglets, barres
de navigation, barres de recherche, etc.).

141

CHAPITRE 9.

FENTRES, VUES ET CONTRLES

Cration d'une application multivues


Avant de nous intresser aux contrles, nous allons consacrer un peu de temps l'tude
des vues. Cette tape est fondamentale. En eet, si les applications les plus simples
comportent une seule vue, il n'est pas rare d'utiliser trois ou quatre vues dans une
application traditionnelle.
Une bonne nouvelle : la quasi-totalit du travail se fera dans Interface Builder. Ce sera
donc un jeu d'enfant pour vous.

Cration de l'application
Commencez par crer une application base sur le modle Single View Application
et donnez-lui le nom  troisVues . Cliquez sur MainStoryboard.storyboard dans le
volet de navigation.
Rappelons que nous voulons crer une application qui comporte trois vues. Un contrleur de vue tant dj prsent dans l'application, vous allez en ajouter deux autres en
eectuant des glisser-dposer de la bibliothque d'objets la zone d'dition d'Interface
Builder. Cliquez sur l'icne Hide or show the Utilities dans la barre d'outils de
Xcode (1), sur l'icne Show the Object library dans la partie infrieure du volet
des utilitaires (2), puis faites glisser deux View Controller sur la zone d'dition (3),
comme indiqu la gure 9.1.

Figure 9.1  Il faut ajouter deux vues l'application

Pour bien reprer chacune des vues, vous allez modier leur couleur d'arrire-plan.
Cliquez sur l'icne Show the Attributes inspector dans le volet des utilitaires et
agissez sur la liste droulante Background. Choisissez alors les couleurs que vous sou142

CRATION D'UNE APPLICATION MULTIVUES

haitez. Pour ma part, j'ai respectivement choisi les couleurs bleu, blanc et vert.
Ensuite, faites glisser :
 un contrle Label sur chacune des vues ;
 un contrle Round Rect Button sur la premire vue et un autre sur la troisime
vue ;
 deux contrles Round Rect Button sur la deuxime vue.
Double-cliquez tour tour sur chacun de ces contrles et ajoutez le texte suivant :
Vue Contrle

1
1
2
2
2
3
3

Label
Round Rect Button
Label
Premier Round Rect Button
Deuxime Round Rect Button
Label
Round Rect Button

Texte

Vue 1
Vue suivante
Vue 2
Vue suivante
Vue prcdente
Vue 3
Vue prcdente

La gure 9.2 reprsente le rsultat que j'ai obtenu.

Figure 9.2  Les trois vues avec les Label et les Round

Rect Button

Pour que ces vues puissent se faire rfrence l'une l'autre, vous allez ajouter un contrleur de navigation.
Cliquez sur la premire vue, droulez le menu Editor, pointez Embed In et cliquez sur
Navigation Controller. Un contrleur de navigation est ajout (gure 9.3), et il est
automatiquement reli la premire vue.
Vous allez maintenant relier les Round Rect Button aux direntes vues. Je vais vous
indiquer en dtail comment procder pour relier le bouton de la vue 1 la vue 2. Vous
143

CHAPITRE 9.

FENTRES, VUES ET CONTRLES

Figure 9.3  Le contrleur est automatiquement reli la vue slectionne

ferez de mme pour relier les autres boutons des autres vues.
Cliquez sur le Round Rect Button de la vue 1 pour le slectionner. Maintenez la touche
Ctrl enfonce, puis glissez-dposez le Round Rect Button sur la vue 2. Au relchement du bouton gauche, une bulle intitule Storyboard Segues est ache. Dans cette
bulle, vous devez choisir le type de transition entre les deux vues :
 Push : transition horizontale ;
 Modal : transition verticale ;
 Custom : transition personnalise.
Choisissez Push pour obtenir une translation horizontale. Une che entre la vue 1 et
la vue 2 indique que la liaison a t tablie (gure 9.4).

Figure 9.4  Une che indique que la liaison a t faite

Recommencez la manipulation qui vient d'tre dcrite pour relier :


 les vues 1 et 2 via le bouton Vue prcdente de la vue 2 ;
 les vues 2 et 3 via le bouton Vue suivante de la vue 2 ;
 les vues 2 et 3 via le bouton Vue prcdente de la vue 3.
a y est, vous pouvez excuter l'application et jouer avec les boutons des trois vues.
144

INSRER UN CONTRLE DANS UNE APPLICATION

Insrer un contrle dans une application


Arrivs ce point, vous savez crer une application multivues, mais vous ne savez pas
encore (du moins pas prcisment) comment ajouter du contenu dans chacune de ces
vues. Il est grand temps de nous intresser aux contrles.
Pour insrer un contrle dans une application, vous devez dans un premier temps
acher la bibliothque de contrles. Comme la gure 9.5, slectionnez le chier
MainStoryboard.storyboard correspondant la vue dans la zone de navigation (1),
cliquez sur l'icne Hide or show the Utilities dans la barre d'outils (2), puis sur
Show the Object Library dans la zone des utilitaires (3). Pointez alors un contrle
dans la bibliothque, maintenez le bouton gauche de la souris enfonc et dposez le
contrle sur la fentre de l'application (4).

Figure 9.5  Insertion d'un contrle dans une application


Pour insrer un contrle dans l'application, vous pouvez galement doublecliquer sur son icne dans la bibliothque.

Si vous n'tes pas certains de la fonction d'un contrle, cliquez dessus dans la bibliothque et maintenez le pointeur de la souris immobile pendant quelques instants. Une
bulle d'aide sera alors ache. Si ces informations ne sont pas susantes, vous pouvez
cliquer sur l'icne Show Quick Help dans la partie suprieure du volet des utilitaires,
145

CHAPITRE 9.

FENTRES, VUES ET CONTRLES

comme indiqu la gure 9.6.

Figure 9.6  Cliquez sur l'icne Show

Quick Help

Si ncessaire, cliquez sur un des liens (achs en bleu) pour accder l'aide correspondante dans la documentation Apple.

Positionner, aligner et redimensionner un contrle


vue
La faon la plus naturelle et la plus rapide pour positionner, aligner et redimensionner
des contrles consiste utiliser la souris.

Positionner un contrle vue


Pour dplacer un contrle dans la vue qui le contient, pointez-le, maintenez le bouton
gauche de la souris enfonc, dplacez la souris jusqu' ce que l'objet ait la position
souhaite puis relchez le bouton gauche de la souris.

Aligner un contrle vue


Les contrles d'une application peuvent tre aligns vue. Ainsi par exemple, il est possible de faire correspondre le bord gauche d'un contrle avec celui d'un autre contrle,
ou encore d'aligner un contrle au centre ou sur une marge de la vue. Pointez le contrle
positionner, maintenez le bouton gauche de la souris enfonc et dplacez le contrle
dans la vue. Une ou plusieurs lignes pointilles signalent le ou les divers alignements
possibles pendant que le contrle est dplac, comme le montre la gure 9.7. Relchez
le bouton gauche lorsque le contrle a la position souhaite.
146

POSITIONNER, ALIGNER ET REDIMENSIONNER UN CONTRLE VUE

Figure 9.7  Des pointills apparaissent pour aligner les dirents lments

Redimensionner un contrle vue


De nombreux contrles peuvent tre redimensionns. Pour cela, il sut d'agir sur leurs
poignes de redimensionnement l'aide de la souris. Cliquez sur le contrle pour le slectionner. Plusieurs poignes de redimensionnement sont aches. Pointez l'une d'entre
elles. Lorsque le pointeur de la souris change de forme, maintenez le bouton gauche
enfonc et dplacez la souris pour obtenir la dimension souhaite (gure 9.8).

Figure 9.8  Il est facile de redimensionner la main un lment

147

CHAPITRE 9.

FENTRES, VUES ET CONTRLES

Un aperu des contrles disponibles

Vous trouverez dans cette section les dirents contrles accessibles dans la bibliothque. Chacun d'eux peut tre utilis dans une application pour iPhone, iPod Touch
et iPad.
Label

: Texte non modiable par l'utilisateur

Round Rect Button

: Bouton de commande touch

Segmented Control

: Onglets permettant d'acher direntes vues /

contrles

Text Field

: Zone de texte modiable par l'utilisateur

Slider

: Curseur pour faciliter la saisie d'une valeur

Switch

: Bouton de type ON/OFF

Activity Indicator View : Indicateur d'activit pour faire patienter l'uti-

lisateur pendant un long traitement


Progress View

ment

: Indicateur de progression utilis pendant un long traite-

: Indique la page en cours de visualisation (dans une application multipage)

Page Control

Table View : Liste hirarchique d'informations textuelles disposes vertica-

lement

148

UN APERU DES CONTRLES DISPONIBLES

Table View Cell


View

: Paramtre d'une des cellules aches dans un Table

Image View : Conteneur permettant d'acher une image ou une animation

Text View

Web View

: Zone de texte multiligne ditable

: Achage d'un contenu Web

Map View : Achage d'une carte, similaire celle ache dans l'application

Plans

Scroll View : Contrle permettant d'acher un contenu d'une taille sup-

rieure celle de la fentre / du contrle en faisant glisser l'achage dans la


zone de visualisation
: Slection d'une date et d'une heure l'aide de plusieurs
contrles en forme de roues
Date Picker

Picker View

: Slection d'une valeur dans un contrle en forme de roue

Ad BannerView

GLKit View

: Vue ddie l'achage de publicits

: Vue OpenGL

Tap Gesture Recognizer

ES

: Reconnaissance d'une gestuelle multitouch

Pinch Gesture Recognizer

: Reconnaissance de la gestuelle  rtrcir 


149

CHAPITRE 9.

FENTRES, VUES ET CONTRLES

Rotation Gesture Recognizer

tion 

Swipe Gesture Recognizer

Pan Gesture Recognizer

: Reconnaissance de la gestuelle  rota-

: Reconnaissance de la gestuelle  glisser 

: Reconnaissance de la gestuelle  glisser 

Long Press Gesture Recognizer

toucher 

: Reconnaissance de la gestuelle  long

Object : Un objet non disponible dans Interface Builder, tir d'une ins-

tance d'une classe

View Controller : Contrle ddi la gestion de barres d'outils, barres de

navigation et vues d'une application

Table View Controller

: Contrle ddi la gestion d'un Table

View

Navigation Controller : Ce contrle est ddi la gestion des contrleurs


de vue. Il fournit des informations relatives la vue active.
Tab Bar Controller

View

: Gre plusieurs vues au travers d'onglets

: Zone rectangulaire de trac

Navigation Bar : Barre de navigation, ache juste en dessous de la barre

d'tat

Navigation Item

150

: lment ach dans un contrle Navigation

Bar

LES VOLETS

Search Bar

ATTRIBUTS

ET

TAILLE

: Barre de recherche ditable

Search Bar and Search Display Controller : Barre de recherche et son


contrleur Table View associ
Toolbar

: Barre d'outils contenant un ou plusieurs boutons

Bar Button Item

: Un bouton dans un contrle Toolbar

Fixed Space Bar Button Item

dans un contrle Toolbar

: Espace ajustable par le programmeur

Flexible Space Bar Button Item : Espace qui s'ajuste automatiquement


en fonction de la place disponible dans un contrle Toolbar
Tab Bar

: Barre d'onglets

Tab Bar Item : Une icne reprsentant un onglet dans un contrle Tab Bar

Les volets Attributs et Taille


Tous ces contrles ont l'air trs intressants, mais est-il possible de les personnaliser ?

Juste avant cette (longue) liste, vous avez vu qu'il tait possible de changer la taille
d'un contrle en agissant sur ses poignes de redimensionnement. Rassurez-vous, la
personnalisation des contrles ne se limite pas leur redimensionnement. De nombreux
autres paramtres sont accessibles en utilisant le volet des attributs. Pour accder ce
volet, cliquez sur l'icne Show the Attributes inspector, dans la partie suprieure
du volet des utilitaires, comme indiqu la gure 9.9.
Je ne vais pas dcrire en dtail tous les paramtres accessibles dans le volet des attributs,
151

CHAPITRE 9.

FENTRES, VUES ET CONTRLES

Figure 9.9  Achage du volet des attributs

d'autant plus qu'ils varient normment d'un contrle l'autre. Ce sera donc vous
de les dcouvrir. Cependant, je ne peux m'empcher de vous donner quelques conseils
pour que vous soyez encore plus ecaces.
 Le volet des attributs concerne le contrle actif. Pour slectionner un contrle, il vous
sut de cliquer dessus.
 Les caractristiques de la vue peuvent galement tre ajustes dans le volet des
attributs : il sut pour cela de cliquer sur un emplacement inoccup de la vue an
d'accder aux paramtres correspondants.
 Pour slectionner facilement un des contrles de l'application, vous pouvez utiliser la
barre d'accs rapide d'Interface Builder (cette barre est situe au-dessus de la zone
d'dition). Cliquez sur l'icne View puis sur le contrle que vous voulez slectionner.
 Pour chaque contrle, le volet des attributs donne accs un grand nombre de
caractristiques. Cependant, les informations relatives la position et la taille ne
sont pas accessibles. Si vous dsirez positionner trs prcisment un contrle, vous
utiliserez le volet Taille. Cliquez sur le contrle concern, puis sur l'icne Show the
Size inspector dans la partie suprieure du volet des utilitaires.

En rsum
 Les iPhone, iPod Touch et iPad ont une particularit : ils ne sont capables d'acher
qu'une et une seule fentre sur l'cran. Cependant, il est possible de dnir plusieurs
vues dans Interface Builder, en glissant-dposant des contrles View Controller
152

LES VOLETS

ATTRIBUTS

ET

TAILLE

depuis la bibliothque d'objets dans le canevas.


 Pour que plusieurs vues puissent se faire rfrence l'une l'autre, vous devez ajouter
un contrleur de navigation (Navigation Controller). Ce dernier est ajout avec
la commande Embed In/Navigation Controller dans le menu Editor de Xcode.
 Pour dnir une transition d'une vue une autre, contrle-glissez-dposez un bouton
de la vue d'origine sur la vue de destination et choisissez un type de transition : Push,
Modal ou Custom.
 Pour ajouter des contrles dans une application multivue, glissez-dposez le contrle
souhait depuis la bibliothque de contrles dans la vue qui doit l'hberger. Les
contrles ainsi dposs peuvent tre dplacs, aligns et redimensionns vue. Vous
pouvez galement utiliser les volets Attributs et Taille pour accder des paramtres complmentaires.
 Pour slectionner facilement un des contrles de l'application, vous pouvez utiliser
la barre d'accs rapide d'Interface Builder, au-dessus du canevas. Cliquez sur l'icne
View puis sur le contrle que vous voulez slectionner.

153

CHAPITRE 9.

154

FENTRES, VUES ET CONTRLES

Chapitre

10

Les contrles qui achent des donnes


(1/2)
Dicult :

ans ce chapitre, nous allons passer en revue les contrles qui achent du texte
et des images sur l'cran. Au l des pages, vous apprendrez les ajouter dans une
application, les personnaliser via Interface Builder, les interfacer (c'est--dire les
rendre accessibles) dans le code Objective-C et les faire vivre avec du code Objective-C.
Ce chapitre et le suivant sont trs importants car ils donnent les bases de toutes vos futures
applications. Je vous suggre de les lire une premire fois, puis d'y revenir lorsque vous
dvelopperez vos propres applications. Vous y trouverez de nombreux exemples pratiques
qu'il vous sura d'adapter vos besoins. Cette adaptation ne ncessitera gnralement
que quelques modications dans le nom des objets utiliss !

155

CHAPITRE 10.

LES CONTRLES QUI AFFICHENT DES DONNES (1/2)

Acher du texte non modiable


Les contrles Label (gure 10.1) sont utiliss pour acher des textes courts sur une
ou plusieurs lignes. Leur contenu ne peut pas tre modi par l'utilisateur. Les caractristiques d'un Label peuvent tre dnies dans Interface Builder, comme le montre
la gure 10.2.

Figure 10.1  L'icne du contrle Label

Figure 10.2  Il est possible de modier les caractristiques d'un Label dans Interface

Builder
Vous pouvez choisir, entre autres, le texte ach dans le label, l'alignement du texte
dans le contrle, le nombre de lignes, la police et la couleur des caractres. En utilisant
du code Objective-C, vous pouvez galement agir sur le texte, la police, la taille et la
couleur des caractres ainsi que la couleur d'arrire-plan d'un label.
1
2
3
4

156

monLabel . text = @ " Un court texte affich dans le contr le Label


sur deux lignes " ;
monLabel . numberOfLines = 2 ;
monLabel . font = [ UIFont fontWithName : @ " Courier " size : 10 . 0f ];
monLabel . textAlignment = UITextAlignmentCenter ;

SAISIR DU TEXTE SUR UNE LIGNE







monLabel . textColor = [ UIColor colorWithRed : 1 . 0f green : 0 . 0f


blue : 0 . 0f alpha : 1 . 0f ];

La premire ligne dnit le texte ach dans le Label.


La deuxime ligne indique que le texte sera ach sur deux lignes.
La troisime ligne dnit la police et la taille des caractres.
La quatrime ligne dnit le mode d'alignement du texte dans le contrle.
Enn, la cinquime ligne dnit la couleur du texte via ses composantes rouge
(colorWithRed), verte (green) et bleue (blue) et sa transparence (alpha).
Les composantes de couleur sont des nombres ottants compris entre 0.0f
et 1.0f. Pour obtenir une des trois couleurs de base (rouge, vert ou bleu),
initialisez cette couleur 1.0f et les deux autres 0.0f. Dans cet exemple,
la composante rouge est initialise 1.0f et les deux autres composantes
0.0f. La couleur obtenue est donc un rouge pur. Quant la transparence,
il s'agit galement d'un nombre ottant compris entre 0.0f (transparent) et
1.0f (opaque).

D'autres mthodes sont disponibles pour manipuler les contrles Label. Pour en avoir
un aperu, consultez la documentation relative la classe UILabel.
Comment avoir une liste complte des polices disponibles sur un device iOS ?

La liste des polices disponibles sur un device iOS est accessible sur le site Web iOS
Fonts.


B

iOS Fonts
Code web :

387967

Saisir du texte sur une ligne


Les Text Field (gure 10.3) sont des zones de texte monoligne. Ils sont utiliss pour
saisir des donnes textuelles courtes, comme un nom ou un mot de passe par exemple.
Le texte saisi dans un contrle Text Field est accessible en lecture et en criture
travers sa proprit text.

Figure 10.3  L'icne du contrle Text

Field

Supposons que vous ayez dni le Label monLabel et le Text Field monTextField.
Pour acher dans le Label le contenu du Text Field chaque fois que ce dernier change,
procdez comme suit :
157

CHAPITRE 10.

LES CONTRLES QUI AFFICHENT DES DONNES (1/2)

1. contrle-glissez-dposez le Label de la fentre d'dition dans le code du chier


d'en-ttes, juste au-dessus du @end nal et crez l'outlet monLabel ;
2. contrle-glissez-dposez le Text Field de la fentre d'dition dans le code du
chier d'en-ttes, juste au-dessus du @end nal et crez l'outlet monTextField ;
3. contrle-glissez-dposez le Text Field de la fentre d'dition dans le code du
chier d'en-ttes, juste au-dessus du @end nal et crez l'action monTextField,
de type Editing Changed ;
4. insrez le code suivant dans la mthode monTextFieldChange :
1
2
3

- ( IBAction ) monTextFieldChange :( id ) sender {


monLabel . text = monTextField . text ;
}

Tout comme pour les Label, vous pouvez choisir l'alignement, la police et la couleur du
texte, dans Interface Builder ou avec du code Objective-C. Pour inviter l'utilisateur
entrer du texte dans un Text Field, vous pouvez renseigner sa proprit Placeholder,
comme indiqu la gure 10.4.

Figure 10.4  Vous pouvez renseigner la proprit Placeholder pour inviter l'utilisa-

teur crire
Cette proprit est galement utilisable en lecture et en criture dans le code :
1

monTextField . placeholder = @ " Entrez votre nom " ;

La premire lettre de la proprit est minuscule. Ceci est une vidence, puisque
les proprits Xcode respectent la convention camelCase, mais cela va mieux
en le disant tout de mme !

158

SAISIR DU TEXTE SUR PLUSIEURS LIGNES

Saisir du texte sur plusieurs lignes


Les Text View (gure 10.5) sont des zones de texte multiligne. Ces contrles peuvent
tre achs en lecture seule ou en lecture/criture. Dans le deuxime cas, l'utilisateur
pourra modier leur contenu en utilisant le clavier du device. Le texte ach dans un
contrle Text View utilise une seule police et une seule taille de caractres. Lorsqu'une
adresse Web est insre dans un Text View, elle peut tre clique par l'utilisateur. La
page correspondante s'ouvre alors dans le navigateur Safari.
Enn, lorsque le contenu d'un Text View est trop long pour tre ach en totalit,
l'utilisateur peut utiliser une gestuelle de glisser pour faire dler le texte dans le
contrle.

Figure 10.5  L'icne du contrle Text

View

Les contrles Text View relvent de la classe UITextView. Consultez l'aide de cette
classe pour en savoir plus sur ce contrle.

Acher une image


Le contrle Image View (gure 10.6) permet d'acher une image ou une animation,
dnie par l'achage conscutif de plusieurs images. Les images sont charges via des
objets UIImage. Une fois l'image charge, il sut de l'associer une vue et une
taille pour l'acher. Sans entrer dans les dtails, sachez cependant que les images
aches dans un contrle Image View peuvent provenir de l'album photo du device,
des ressources de l'application, d'Internet ou tre cres par l'application elle-mme.
Examinons ces quatre cas.

Figure 10.6  L'icne du Image

View

L'image est dans l'album photo du device


Certains devices iOS disposent d'un appareil photo. Lorsqu'une photo est prise, elle
est stocke dans l'album photo du device. Ce dernier est accessible par l'icne Photos.
Malheureusement, lorsque vous cliquez dessus dans le simulateur iOS, l'album photo
est vide, comme la gure 10.7.
Si vous voulez utiliser le simulateur pour vous entraner manipuler les photos de
l'album, il est donc ncessaire de le remplir avant toute chose. Le simulateur vous
159

CHAPITRE 10.

LES CONTRLES QUI AFFICHENT DES DONNES (1/2)

Figure 10.7  Sur le simulateur, l'album photo est vide

propose d'utiliser iTunes pour ajouter des photos dans l'album. Nous allons utiliser
une tout autre technique.
1. Trouvez un dossier qui contient des photos sur votre Mac.
2. Glissez-dposez une photo sur l'album photo du simulateur. Quelques instants
plus tard, la photo est ache dans le navigateur Safari (1).
3. Pointez la photo et maintenez le bouton gauche de la souris enfonc jusqu' ce
qu'un menu apparaisse dans la partie infrieure de l'cran (2).
4. Cliquez sur Save Image (3).
5. Recommencez les tapes 2 4 pour ajouter une ou plusieurs autres photos.
Si vous avez du mal comprendre, reprenez ces instructions en observant la gure 10.8.
Maintenant, voyons comment accder ces photos.
Toute la magie rside dans l'utilisation d'un objet UIImagePickerController. Ce
contrleur permet entre autres de slectionner une image dans une liste. C'est exactement ce que nous voulons. La liste sera prise dans l'album photo.
Dnissez un nouveau projet de type Single View Application et donnez-lui le nom
 imagePicker . Cliquez sur MainStoryboard.storyboard dans le volet de navigation,
puis ajoutez un contrle Image View et un contrle Rounded Rect Button dans la zone
d'dition. Redimensionnez-les pour obtenir quelque chose ressemblant la gure 10.9.
Reliez les deux contrles au code en crant :
160

AFFICHER UNE IMAGE

Figure 10.8  Il est possible d'ajouter des photos facilement dans le simulateur

Figure 10.9  Placement des lments

161

CHAPITRE 10.

LES CONTRLES QUI AFFICHENT DES DONNES (1/2)

 l'outlet uneImage pour le contrle UIImageView ;


 l'action album pour le bouton.
Le chier ViewController.h devrait maintenant ressembler ceci :
1
2
3
4
5
6
7

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
@property ( weak , nonatomic ) IBOutlet UIImageView * uneImage ;
- ( IBAction ) album :( id ) sender ;
@end

tant donn que l'objet UIImagePickerController ne fait pas partie de la librairie


d'objets Cocoa Touch, nous allons l'implmenter directement dans le code. Cliquez sur
ViewController.h dans le volet de navigation et insrez la ligne suivante dans les
variables d'instance :
UIImagePickerController * picker ;

Le chier ViewController.h devrait maintenant ressembler ceci :


1
2
3
4
5
6
7
8
9
10
11

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
{
UIImagePickerController * picker ;
}
@property ( weak , nonatomic ) IBOutlet UIImageView * uneImage ;
- ( IBAction ) album :( id ) sender ;
@end

Lorsque l'utilisateur clique sur le bouton, nous voulons acher la liste des images
contenues dans l'album photo. Pour cela, nous allons agir sur la mthode vnementielle
album. Cliquez sur ViewController.m dans le volet de navigation puis compltez la
mthode album comme suit :
1
2
3
4
5
6

- ( IBAction ) album :( id ) sender {


picker = [[ UIImagePickerController alloc ] init ];
picker . delegate = self ;
picker . sourceType =
UIImagePickerControllerSourceTypePhotoLibrary ;
[ self presentModalViewController : picker animated : YES ];
}

Si vous trouvez ce code compliqu, ne paniquez pas ; je vais tout vous expliquer !
La ligne 2 initialise l'objet picker en le reliant la classe UIImagePickerController.
La ligne 3 dnit le delegate de l'objet picker. C'est ce delegate qui recevra les notications lorsque l'utilisateur slectionnera une image ou fermera l'Image Picker sans
rien slectionner.
162

AFFICHER UNE IMAGE

La ligne 4 indique l'Image Picker quel endroit il doit rechercher la liste d'images.
Vous l'aurez compris, le mot UIImagePickerControllerSourceTypePhotoLibrary fait
rfrence l'album photo.
Enn, la ligne 5 applique la mthode presentModalViewController l'Image Picker.
Ainsi, les vignettes de l'album seront aches dans une fentre  modale , c'est--dire
dans une fentre situe au-dessus de l'application et qui rend l'accs cette dernire
impossible.
Si vous remplacez UIImagePickerControllerSourceTypePhotoLibrary
par UIImagePickerControllerSourceTypeCamera, le device prend une
photo et la prsente dans l'Image Picker.

Je ne sais pas si vous avez remarqu le point d'exclamation de couleur jaune en face
de l'instruction picker.delegate = self;. Il s'agit d'un avertissement. Si vous cliquez sur le point d'exclamation, Xcode ache des informations complmentaires sur le
problme, comme la gure 10.10.

Figure 10.10  Xcode ache des informations complmentaires sur le problme

Reprenons l'intitul du message :


Passing ' ViewController * const \ _strong ' to parameter of
incompatible type 'id < UINavigationControllerDelegate ,
UIImagePickerControllerDelegate >'
Assigning to 'id < UINavigationControllerDelegate .
UIImagePickerControllerDelegate >' from incompatible type '
imagePickerViewController * '

Cela signie que la gestion des vnements lis l'objet picker ne peut pas tre prise
en charge dans cette classe (= self dans l'instruction).
En d'autres termes, cela signie qu'il faut ajouter un delegate dans le chier d'en-ttes
pour traiter ces vnements. Et mme deux delegate, puisque UIImagePickerController
est li UINavigationController.
Pour rgler ce problme, retournez dans le chier ViewController.h et modiez la
dclaration de l'interface comme suit :
1
2
3

@interface ViewController : UIViewController <


UINavigationControllerDelegate ,
UIImagePickerControllerDelegate > {
...
}

163

CHAPITRE 10.

LES CONTRLES QUI AFFICHENT DES DONNES (1/2)

Comme par magie, l'avertissement disparat. En dnissant ces deux delegate, nous
avons indiqu au compilateur que les notications reues lors des manipulations de
l'utilisateur dans l'Image Picker seront prises en compte par. . . ces delegate et traits
dans la classe de l'application.
Vous pouvez lancer l'application. Lorsque vous cliquez sur le bouton Accder l'album
photo, l'album photo apparat dans une liste. Cliquez dessus pour acher les vignettes
qui reprsentent son contenu, comme la gure 10.11.

Figure 10.11  Cliquez sur les vignettes

Consternation ! Lorsque vous cliquez sur une image, elle ne s'ache pas sur le device !
Si vous rchissez un peu, c'est tout fait normal. . . puisqu'aucune mthode n'a t
crite pour provoquer cet achage. Dnissez donc la mthode suivante :
1
2
3
4
5

- ( void ) imagePickerController :( UIImagePickerController *)


Picker didFinishPickingMediaWithInfo :( NSDictionary *) info
{
uneImage . image = [ info objectForKey :
UIImagePickerControllerOriginalImage ];
[ picker dismissModalViewControllerAnimated : YES ];
}

Cette mthode est excute lorsque l'utilisateur choisit une vignette dans l'Image
Picker. L'image choisie est alors ache dans le contrle Image View (ligne 3 du
code).
L'instruction suivante ferme la vue modale de l'Image Picker.
Tout cela, c'est trs intressant, mais comment est-ce que j'aurais pu trouver
cette mthode tout seul ? Je ne me vois vraiment pas l'inventer !

164

AFFICHER UNE IMAGE

Dans tous vos dveloppements d'applications iOS, la documentation Apple vous sera
d'une trs grande aide. Pour l'utiliser, posez-vous les questions suivantes :  Qu'est-ce
que je veux faire ?  et  De quoi dpend l'action que je veux raliser ? .
Ici par exemple, vous voulez acher une image dans le contrle ImageView lorsque
l'utilisateur clique sur une vignette ache dans l'Image Picker. Vous voulez donc
capturer un vnement. Et comme vous le savez, les vnements sont grs par. . . les
delegate ! C'est donc dans l'aide Apple sur un delegate que va se trouver la solution.
De quel delegate s'agit-il ? Eh bien, l'utilisateur va cliquer sur une vignette dans le
contrle Image Picker. Il s'agit donc du delegate UIImagePickerControllerDelegate.
Comme indiqu la gure 10.12, cliquez sur l'icne Organizer (1), dans l'angle suprieur droit de la fentre Xcode pour acher la fentre d'aide. Tapez  UIImagePickerControllerDelegate
 dans la zone de texte Rechercher (2) et appuyez sur la touche

Entre
de
votre
clavier.
Plusieurs rponses sont aches dans le volet gauche. Choi

sissez celle qui se trouve sous l'intitul  Reference  (3). a y est, vous avez fait le
plus gros du travail. Il ne vous reste plus qu' parcourir la page d'aide pour trouver la
mthode recherche (4).

Figure 10.12  Suivez ces instructions pour faire une recherche dans la documentation

Pour nir, vous devez implmenter une autre mthode, qui sera excute si l'utilisateur
clique sur Cancel pour annuler l'utilisation de l'Image Picker. Dans ce cas, il sura
de fermer la vue modale et de supprimer l'objet Picker. Voici le code utiliser :
1

- ( void ) imagePickerControllerDidCancel :( UIImagePickerController


*) Picker

165

CHAPITRE 10.

2
3
4
5

{
}

LES CONTRLES QUI AFFICHENT DES DONNES (1/2)

[ picker dismissModalViewControllerAnimated : YES ];


uneImage . image = nil ;

La ligne 3 ferme la vue modale de l'Image


ache dans le contrle Image View.

Picker. Quant la ligne 4, elle eace l'image

La mthode imagePickerControllerDidCancel a galement t trouve


dans l'aide Apple sur le delegate UIImagePickerControllerDelegate.

L'application est entirement oprationnelle. Il ne vous reste plus qu' l'excuter et


choisir l'image acher.

L'image est dans les ressources de l'application


Une application iOS peut  embarquer  un ou plusieurs chiers (images, sons, textes,
etc.). Dans ce cas, on dit que ces chiers font partie des ressources de l'application.
Avant toute chose, il va nous falloir ajouter des ressources l'application. Pour ce
faire, cliquez du bouton droit sur l'icne qui reprsente l'application dans le volet de
navigation et choisissez New group dans le menu contextuel, comme la gure 10.13.

Figure 10.13  Choisissez New

group

dans le menu contextuel

Donnez le nom  Resources  au nouveau groupe (avec un seul  s ). Maintenant, il vous
sut de glisser-dposer une image depuis le Finder dans le dossier  Resources , de
cocher la case Copy items into destination group's folder (if needed) et de
166

AFFICHER UNE IMAGE

valider en cliquant sur Finish (gure 10.14). L'image est alors intgre aux ressources
de l'application.

Figure 10.14  Il est possible d'ajouter des images dans les ressources de l'application

Lorsqu'une image se trouve dans les ressources de l'application (1), elle est directement
accessible dans la proprit Image d'un contrle Image View (2), comme le montre la
gure 10.15.
Vous pouvez galement insrer une image dans un contrle Image View en utilisant du
code. Supposons que l'outlet monImage ait t cr pour reprsenter un contrle Image
View et que l'image chien.jpg se trouve dans les ressources de l'application. Pour
acher cette image dans le contrle Image View, vous utiliserez l'instruction suivante :
1

monImage . image = [ UIImage imageNamed : @ " chien . jpg " ];

Simple, non ?

L'image est sur Internet


Supposons que vous vouliez acher dans un contrle Image View l'image qui se trouve
l'adresse http://www.siteduzero.com/uploads/fr/ftp/iphone/zozor.png.
Commencez par crer un nouveau projet de type Single View Application et donnezlui le nom  imageURL . Cliquez sur MainStoryboard.storyboard dans le volet de
navigation, insrez un contrle Image View dans le canevas et faites-lui occuper toute
la surface disponible. Achez le chier d'en-ttes ct du canevas en cliquant sur
l'icne Show the Assistant editor dans la barre d'outils. Contrle-glissez-dposez le
contrle Image View juste avant le @end du chier d'en-ttes et crez l'outlet monImage.
167

CHAPITRE 10.

LES CONTRLES QUI AFFICHENT DES DONNES (1/2)

Figure 10.15  L'image est accessible dans la proprit Image

Le chier imageURLViewController.h doit maintenant ressembler ceci :


1
2
3
4
5
6

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
@property ( weak , nonatomic ) IBOutlet UIImageView * monImage ;
@end

Pour acher l'image ds l'ouverture de l'application, vous allez agir sur la mthode
viewDidLoad. Cliquez sur ViewController.m dans le volet de navigation et insrez le
code suivant dans la mthode viewDidLoad :
1
2
3
4
5
6

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
NSURL * uneImage = [ NSURL URLWithString : @ " http :// www .
siteduzero . com / uploads / fr / ftp / iphone / zozor . png " ];
monImage . image = [ UIImage imageWithData : [ NSData
dataWithContentsOfURL : uneImage ]];
}

Comme vous pouvez le voir, deux instructions ont t ajoutes cette mthode.
La premire dnit l'objet uneImage de type NSURL et y stocke l'URL de l'image en
utilisant la mthode URLWithString.
La deuxime instruction lit l'image sur le Web et l'aecte l'objet monImage. Remarquez le chanage des messages. Dans un premier temps, un objet NSData est ini168

AFFICHER UNE IMAGE

tialis avec l'image lue sur le Web ([NSData dataWithContentsOfURL: uneImage]).


Dans un deuxime temps, cet objet est transform en un objet UIImage ([UIImage
imageWithData: ...]. Enn, dans un troisime temps, cet objet UIImage est aect
au UIImageView monImage (monImage.image = ...).
Vous pouvez lancer l'application, l'image est immdiatement ache, comme la gure
10.16.

Figure 10.16  Zozor se lance au dmarrage de l'application :-)

L'image est stocke dans la sandbox


Sur un device iOS, chaque application s'excute dans une sandbox 1 qui lui est propre.
Dans cet espace, il est possible de sauvegarder des informations de tous types : textes,
images, URL, etc. Ces informations peuvent tre rapidement retrouves par l'application lorsqu'elle en a besoin. Cette technique est trs pratique. Elle est gnralement
utilise pour stocker l'tat de l'application. Lorsqu'elle est nouveau excute, l'utilisateur la retrouve dans le mme tat que la dernire fois qu'il l'a utilise. Dans cette
section, je vais vous montrer comment stocker et lire une image dans la sandbox. titre
d'exemple, l'image sera lue sur le Web, sauvegarde dans la sandbox de l'application,
puis ache dans un Image View en la lisant dans la sandbox.
Dnissez un nouveau projet de type Single View Application et donnez-lui le nom
 sandbox . Cliquez sur MainStoryboard.storyboard dans le volet de navigation,
1.

Sandbox signie  bac sable  en franais.

169

CHAPITRE 10.

LES CONTRLES QUI AFFICHENT DES DONNES (1/2)

insrez un contrle Image View dans la zone d'dition et faites-lui occuper toute la
surface disponible. Achez le chier d'en-ttes ct de la zone d'dition en cliquant sur
l'icne Show the Assistant editor dans la barre d'outils. Contrle-glissez-dposez le
contrle Image View juste avant le @end du chier d'en-ttes et crez l'outlet monImage.
Le chier ViewController.h doit maintenant ressembler ceci :
1
2
3
4
5
6

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
@property ( weak , nonatomic ) IBOutlet UIImageView * monImage ;
@end

Il est temps de s'attaquer au chier .m. Cliquez sur ViewController.m dans le volet
de navigation et compltez la mthode viewDidLoad comme suit :
1
2
3
4
5

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
// R cup ration du fichier dans la sandbox et affichage dans
le Image View
NSString * limage = [ NSHomeDirectory ()
stringByAppendingPathComponent : @ " Documents / image . png " ];
UIImage * recup = [ UIImage imageWithContentsOfFile : limage ];
monImage . image = recup ;

6
7
8
9
10
11
12
13
14
15

// Stockage d ' une image Web dans la sandbox sous le nom " image
. png "
NSURL * uneImage = [ NSURL URLWithString : @ " http :// www .
siteduzero . com / uploads / fr / ftp / iphone / zozor . png " ];
UIImage * img = [ UIImage imageWithData : [ NSData
dataWithContentsOfURL : uneImage ]];
NSData * imageData = UIImagePNGRepresentation ( img ) ;
[ imageData writeToFile : limage atomically : NO ];

Copier ce code
B
Code web : 648113


Toutes ces instructions ont de quoi donner la chair de poule ! Mais rassurez-vous, elles
n'ont rien de bien sorcier et d'ici cinq petites minutes, vous les comprendrez parfaitement. Comme vous pouvez le voir, cette mthode contient deux blocs d'instructions.
1. Le premier retrouve l'image stocke dans la sandbox et l'ache dans le contrle
Image View.
2. Le deuxime rcupre une image sur le Web et la stocke dans la sandbox sous le
nom image.png.
Examinons les instructions de ces deux blocs. Le chemin du dossier dans lequel sont
stocks les chiers de la sandbox est retourn par la mthode NSHomeDirectory().
170

AFFICHER UNE IMAGE

ce chemin, on ajoute le sous-dossier Documents et le chier image.png. La concatnation se fait via la mthode stringByAppendingPathComponent. Le chemin complet du
chier image.png est donc obtenu par l'expression suivante :
1

[ NSHomeDirectory () stringByAppendingPathComponent : @ " Documents /


image . png " ];

Pour faciliter la manipulation de ce chemin, il est stock dans un objet NSString de


nom limage :
1

NSString * limage = [ NSHomeDirectory ()


stringByAppendingPathComponent : @ " Documents / image . png " ];

Pour rcuprer l'image qui a t stocke cet emplacement, il sut d'utiliser la mthode
imageWithContentsOfFile. L'image est stocke dans un objet UIImage de nom recup :
1

UIImage * recup = [ UIImage imageWithContentsOfFile : limage ];

L'tape nale consiste aecter l'objet recup la proprit image du contrle Image
View, ce qui provoque l'achage de l'image :
1

monImage . image = recup ;

Jusque-l, tout va bien. Attaquons-nous au stockage de l'image dans la sandbox. La premire instruction dnit l'objet NSURL uneImage et y stocke l'adresse URL de l'image
rapatrier depuis le Web :
1

NSURL * uneImage = [ NSURL URLWithString : @ " http :// www . siteduzero


. com / uploads / fr / ftp / iphone / zozor . png " ];

La deuxime instruction rapatrie l'image Web et la stocke dans un objet UIImage de


nom img :
1

UIImage * img = [ UIImage imageWithData : [ NSData


dataWithContentsOfURL : uneImage ]];

Cette technique a dj t tudie dans la section prcdente. C'est pourquoi nous ne


nous y attarderons pas. Malheureusement, il est impossible de stocker un objet UIImage
dans la sandbox. Il faut au pralable le convertir en un objet NSData. Pour cela, vous
utiliserez la mthode :
 UIImagePNGRepresentation si l'image est au format PNG ;
 UIImageJPEGRepresentation si l'image est au format JPEG.
Ici, l'image tant au format PNG, nous utilisons la mthode suivante :
1

NSData * imageData = UIImagePNGRepresentation ( img ) ;

Il ne reste plus qu' enregistrer l'objet


mthode writeToFile :
1

NSData imageData

dans la

sandbox

avec la

[ imageData writeToFile : limage atomically : NO ];

171

CHAPITRE 10.

LES CONTRLES QUI AFFICHENT DES DONNES (1/2)

Lancez l'application.
Lors de la premire excution, l'cran reste dsesprment blanc. Quelle en est la raison
selon vous ? Rappelez-vous : le premier bloc d'instructions ache l'image stocke dans
la sandbox et le deuxime stocke l'image de Zozor dans la sandbox. Lors de la premire
excution, Zozor n'a pas encore t mmoris dans la sandbox. Quittez le simulateur
avec la commande Quitter Simulateur iOS dans le menu Simulateur iOS et relancez l'application en cliquant sur Run dans Xcode. Cette fois-ci, Zozor est bien ach
dans le contrle Image View.
Vous trouverez ci-aprs les codes de cette application.
ViewController.h
1
2
3
4
5
6

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
@property ( weak , nonatomic ) IBOutlet UIImageView * monImage ;
@end

ViewController.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# import " ViewController . h "


@implementation ViewController
@synthesize monImage ;
- ( void ) didReceiveMemoryWarning
{
[ super didReceiveMemoryWarning ];
// Release any cached data , images , etc that aren 't in use .
}
# pragma mark - View lifecycle
- ( void ) viewDidLoad
{
[ super viewDidLoad ];
// R cup ration du fichier dans la sandbox et affichage dans
le Image View
NSString * limage = [ NSHomeDirectory ()
stringByAppendingPathComponent : @ " Documents / image . png " ];
UIImage * recup = [ UIImage imageWithContentsOfFile : limage ];
monImage . image = recup ;

23

172

// Stockage d ' une image Web dans la sandbox sous le nom


image . png
NSURL * uneImage = [ NSURL URLWithString : @ " http :// www .
siteduzero . com / uploads / fr / ftp / iphone / zozor . png " ];

AFFICHER UNE IMAGE

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

UIImage * img = [ UIImage imageWithData : [ NSData


dataWithContentsOfURL : uneImage ]];
NSData * imageData = UIImagePNGRepresentation ( img ) ;
[ imageData writeToFile : limage atomically : NO ];

- ( void ) viewDidUnload
{
[ self setMonImage : 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

Copier ce code
B
Code web : 860881

173

CHAPITRE 10.

LES CONTRLES QUI AFFICHENT DES DONNES (1/2)

En rsum
 Les contrles Label sont utiliss pour acher des textes courts sur une ou plusieurs
lignes. Leur contenu ne peut pas tre modi par l'utilisateur. Les caractristiques
d'un Label peuvent tre dnies dans Interface Builder ou dans le code.
 Les Text Field sont des zones de texte monoligne. Ils sont utiliss pour saisir des
donnes textuelles courtes, telles qu'un nom ou un mot de passe par exemple.
 Le texte saisi dans un contrle Text Field est accessible en lecture et en criture
travers sa proprit text.
 Si vous avez besoin d'une zone de texte multilignes, utilisez des contrles Text View.
 Le contrle Image View permet d'acher une image ou une animation. Les images
peuvent tre charges partir de l'album photo, des ressources de l'application, du
Web ou encore de la sandbox.

174

Chapitre

11

Les contrles qui achent des donnes


(2/2)
Dicult :

ans le chapitre prcdent, nous avons appris travailler avec des contrles lis du
texte et des images. Mais peut-tre aimeriez-vous travailler sur d'autres contrles.
C'est justement ce que je vais vous montrer dans ce chapitre.
Nous allons voir comment acher un contenu Web, une carte, ou encore demander son
avis l'utilisateur. Et, tout comme pour le chapitre prcdent, n'hsitez pas vous reporter
celui-ci lors de vos futurs dveloppements d'applications an d'avoir un cas concret sous
les yeux.

175

CHAPITRE 11.

LES CONTRLES QUI AFFICHENT DES DONNES (2/2)

Acher du contenu Web


Le contrle Web
application.

View

(gure 11.1) est utilis pour intgrer du contenu Web dans une

Figure 11.1  L'icne du contrle Web

View

Pour acher une page Web, vous appliquerez la mthode loadRequest ce contrle.
Par exemple, pour acher le moteur de recherche Google dans un contrle Web View
nomm wv, vous utiliserez l'instruction suivante :
1

[ wv loadRequest :[ NSURLRequest requestWithURL : [ NSURL


URLWithString : @ " http :// www . google . fr " ]]];

La syntaxe est un peu surprenante, je vous l'accorde, mais il  sut  de dire que :
 la mthode loadRequest s'applique sur un objet de type NSURLRequest ;
 un objet NSURLRequest est obtenu en appliquant la mthode requestWithURL sur
un objet de type NSURL ;
 un objet NSURL est obtenu en appliquant la mthode URLWithString sur une chane
de caractres contenant l'adresse URL dsire.
Ainsi, le message le plus interne ([NSURL URLWithString:@"http://www.google.fr"])
dnit un objet de type NSURL et l'initialise avec l'URL de Google :
1

[ NSURL URLWithString : @ " http :// www . google . fr " ]

Cet objet est pass la mthode


NSURLRequest :
1

requestWithURL

qui est applique sur un objet

[ NSURLRequest requestWithURL : objet NSURL ];

Enn, l'objet retourn est pass la mthode loadRequest qui est applique l'objet
Web View wv :
1

[ wv loadRequest : objet NSURLRequest ];

Cette instruction se place dans le chier d'en-ttes de votre application, comme ceci :
1
2
3
4
5

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
[ wv loadRequest :[ NSURLRequest requestWithURL : [ NSURL
URLWithString : @ " http :// www . google . fr " ]]];
}

Il ne vous reste alors plus qu' lancer l'application : vous venez de crer un navigateur
Web qui dmarre automatiquement sur le moteur de recherche Google !
176

AFFICHER UNE CARTE

Acher une carte


Le contrle Map
tion Maps.

View

(gure 11.2) permet d'acher une carte, comme dans l'applica-

Figure 11.2  L'icne du contrle Map

View

En utilisant les mthodes de la classe MKMapView, vous pouvez, entre autres, centrer
la carte sur une coordonne spcique, choisir la taille de la zone acher ou encore
ajouter des informations personnalises sur la carte.
Dans cette section, je vais vous montrer comment acher la carte centre sur Paris. Le
but du jeu est d'acher quelque chose ressemblant la gure 11.3 sur votre device.

Figure 11.3  Paris est centr sur la carte

Dnissez un nouveau projet de type Single View Application et donnez-lui le nom


 map . Une fois n'est pas coutume, nous n'allons pas utiliser Interface Builder dans
ce projet !
177

CHAPITRE 11.

LES CONTRLES QUI AFFICHENT DES DONNES (2/2)

Ajout du framework MapKit l'application


Pour pouvoir acher une carte dans la fentre de votre application, vous devez ajouter le framework MapKit l'application. Pour ce faire, rien de plus simple : lisez les
instructions suivantes en vous aidant de la gure 11.4.
 Slectionnez la premire entre dans le volet de navigation. Ici, l'entre map (1).
 Slectionnez l'onglet Build Phases dans le volet droit (2).
 Dveloppez le dossier Link Binary with Libraries (3).
 Cliquez sur + (4).
 Ajoutez le framework dsir (5).
 Validez en cliquant sur Add (6).

Figure 11.4  Pour acher une carte dans une application, il lui faut le framework
MapKit

Modication du chier .h
Cliquez sur ViewController.h dans le volet de navigation et ajoutez une instruction
#import pour accder au framework MapKit :
1

# import < MapKit / MapKit .h >

Dclarez ensuite un objet de type MKMapView :


178

AFFICHER UNE CARTE

MKMapView * mapView ;

Si vous avez suivi mes indications, le chier mapViewController.h devrait maintenant


avoir l'allure suivante :
1
2
3
4
5
6
7
8
9

# import < UIKit / UIKit .h >


# import < MapKit / MapKit .h >
@interface ViewController : UIViewController
{
MKMapView * mapView ;
}
@end

Modication du chier .m
Cliquez sur ViewController.m dans le volet de navigation. Vous allez maintenant initialiser, personnaliser et acher l'objet mapView. Ce traitement se fera dans la mthode
viewDidLoad. Compltez cette mthode comme ceci :
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

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
// Instancier la carte
mapView = [[ MKMapView alloc ] initWithFrame : self . view . bounds ];
// D finir le zoom
MKCoordinateSpan span ;
span . latitudeDelta = 0 . 5 ;
span . longitudeDelta = 0 . 5 ;
// D finir les coordonn es de Paris
CLLocationCoordinate2D parisCoordinates ;
parisCoordinates . latitude = 48 . 858391 ;
parisCoordinates . longitude =2 . 35279 ;
MKCoordinateRegion parisRegion ;
parisRegion . span = span ;
parisRegion . center = parisCoordinates ;
// Centrer la carte sur Paris
[ mapView setRegion : parisRegion animated : TRUE ];

// Ajouter la carte la vue


[ self . view insertSubview : mapView atIndex : 0 ];

179

CHAPITRE 11.

LES CONTRLES QUI AFFICHENT DES DONNES (2/2)

Copier ce code
B
Code web : 932827


Cela fait beaucoup d'instructions n'est-ce pas ? Examinons-les calmement et vous verrez
qu'il n'y a rien d'insurmontable. . .
L'instruction de la ligne 6 rserve l'espace ncessaire en mmoire pour loger l'objet
MKMapView mapView. Il n'y a rien de sorcier l-dedans : c'est juste la syntaxe (un peu
lourde je vous l'accorde !) utiliser :
mapView = [[ MKMapView alloc ] initWithFrame : self . view . bounds ];

Le premier message rserve la mmoire pour un objet MKMapView ([MKMapView alloc]).


Le deuxime message utilise la mthode initWithFrame pour dnir les dimensions du
rectangle dans lequel sera ache la vue. Ici, self.view.bounds signie la taille de la
vue courante.
Le bloc d'instructions suivant dnit la structure span de type MKCoordinateSpan :
MKCoordinateSpan span ;

Par son intermdiaire, on dnit le nombre de degrs en latitude (c'est--dire du nord


au sud) et en longitude (c'est--dire de l'ouest l'est) de la zone d'achage :
1
2

span . latitudeDelta = 0 . 5 ;
span . longitudeDelta = 0 . 5;

titre d'information :
 1 degr de latitude correspond environ 111 kilomtres.
 1 degr de longitude correspond environ 111 kilomtres l'quateur et 0 kilomtre
aux ples.
Le bloc d'instructions suivant dnit les coordonnes de la ville de Paris. Pour cela, la
structure parisCoordinates, de type CLLocationCoordinate2D est instancie :
CLLocationCoordinate2D parisCoordinates ;

Puis les coordonnes de la ville de Paris y sont stockes :


parisCoordinates . latitude = 48 . 833 ;
parisCoordinates . longitude = 2 . 333 ;

1
2

Pour avoir les coordonnes d'un endroit du globe, vous pouvez vous rendre sur
Google Maps. Une fois repr l'endroit, faites un clic droit avec votre souris
et cliquez sur Plus d'infos sur cet endroit. Dans le champ texte audessus de la carte, les coordonnes s'achent.

Google Maps
B
Code web : 475144


Le bloc d'instructions suivant dnit le centre de l'achage et le niveau de dtail. Pour
cela, la structure parisRegion de type MKCoordinateRegion est instancie :
180

AFFICHER UNE CARTE

MKCoordinateRegion parisRegion ;

Puis le niveau de dtail est prcis en faisant rfrence la structure map dnie prcdemment :
1

parisRegion . span = span ;

Le centre de l'achage est dni en faisant rfrence la structure parisCoordinates


dnie prcdemment :
1

parisRegion . center = parisCoordinates ;

Il ne reste plus qu' envoyer un message l'objet mapView pour lui demander d'acher
la rgion dnie dans la structure parisRegion dnie prcdemment. Ici, le paramtre
animated tant initialis TRUE, l'achage se fera avec une animation :
1

[ mapView setRegion : parisRegion animated : TRUE ];

Pour terminer, la vue mapView est ajoute l'application, ce qui provoque son achage :
1

[ self . view insertSubview : mapView atIndex : 0 ];

Et comme vous avez t sages, je vous donne les codes de l'application. :-)
ViewController.h
1
2
3
4
5
6
7
8
9

# import < UIKit / UIKit .h >


# import < MapKit / MapKit .h >
@interface ViewController : UIViewController
{
MKMapView * mapView ;
}
@end

ViewController.m
1
2
3
4
5
6
7
8
9
10
11
12
13

# import " ViewController . h "


@implementation ViewController
- ( void ) didReceiveMemoryWarning
{
[ super didReceiveMemoryWarning ];
// Release any cached data , images , etc that aren 't in use .
}
# pragma mark - View lifecycle
- ( void ) viewDidLoad

181

CHAPITRE 11.

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

LES CONTRLES QUI AFFICHENT DES DONNES (2/2)

[ super viewDidLoad ];
// instancier la carte
mapView = [[ MKMapView alloc ] initWithFrame : self . view . bounds ];
// d finir le zoom
MKCoordinateSpan span ;
span . latitudeDelta = 0 . 5;
span . longitudeDelta = 0 . 5;
// d finir les coordonn es de Paris
CLLocationCoordinate2D parisCoordinates ;
parisCoordinates . latitude = 48 . 858391 ;
parisCoordinates . longitude = 2 . 35279 ;
MKCoordinateRegion parisRegion ;
parisRegion . span = span ;
parisRegion . center = parisCoordinates ;
// centrer la carte sur Paris
[ mapView setRegion : parisRegion animated : TRUE ];

// ajouter la carte la vue


[ self . view insertSubview : mapView atIndex : 0 ];

- ( void ) viewDidUnload
{
[ 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
{

182

QUAND LE CONTENU DPASSE LA TAILLE DU CONTRLE, DE LA VUE OU


DE LA FENTRE

64
65
66
67
68
69
70
71
72
73

[ super viewDidDisappear : animated ];

- ( BOOL ) shouldAutorotateToInterfaceOrientation :(
UIInterfaceOrientation ) interfaceOrientation
{
// Return YES for supported orientations
return ( interfaceOrientation !=
UIInterfaceOrientationPortraitUpsideDown ) ;
}
@end

Copier ce code
Code web : 548736

Quand le contenu dpasse la taille du contrle, de la


vue ou de la fentre
Vous utiliserez un contrle Scroll View (gure 11.5) pour acher un contenu qui est
plus grand que la fentre de l'application. Les utilisateurs pourront alors faire glisser la
fentre de visualisation sur le contenu, mais aussi zoomer vers l'avant et vers l'arrire
en pinant/tirant l'cran avec deux doigts.

Figure 11.5  L'icne du contrle Scroll

View

Pour illustrer le fonctionnement de ce contrle, nous allons y insrer un contrle Image


View de taille suprieure celle du Scroll View. L'utilisateur pourra alors se dplacer

dans l'image en utilisant des gestuelles de glisser.


Dnissez un projet de type Single View Application et donnez-lui le nom  usv .
Dans le volet de navigation, cliquez sur MainStoryboard.storyboard, puis ajoutez un
contrle Scroll View au canevas de l'application.
Cliquez sur l'icne Show the Assistant editor dans la barre d'outils de Xcode,
contrle-glissez-dposez le contrle Scroll View du canevas sur le chier d'en-ttes,
juste au-dessus de l'instruction @end et dnissez l'outlet scrollView.
Le chier d'en-ttes doit maintenant avoir l'allure suivante :
1
2
3
4
5
6

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
@property ( weak , nonatomic ) IBOutlet UIView * scrollView ;
@end

183

CHAPITRE 11.

LES CONTRLES QUI AFFICHENT DES DONNES (2/2)

Comme la gure 11.6, vous allez maintenant superposer une image au contrle Scroll
View :
 dposez un contrle Image View sur le contrle Scroll View (1) ;
 choisissez une image de grande taille et insrez-la dans les ressources de l'application
(2) ;
 aectez-la au contrle Image View en agissant sur sa proprit Image (3) ;
 visualisez la partie suprieure gauche de l'image en choisissant Top Left dans la liste
droulante Mode (4).

Figure 11.6  On prpare notre application avec une image de grande taille

Slectionnez le chier ViewController.m dans le volet de navigation et compltez la


mthode viewDidLoad comme suit :
1
2
3
4
5
6

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
[ scrollView setScrollEnabled : YES ];
[ scrollView setContentSize : CGSizeMake ( 819 , 1024 ) ];
}

Le premier message destin l'objet scrollView autorise les scrollings :


1

[ scrollView setScrollEnabled : YES ];

Le deuxime dnit la taille du scrolling. Ici, elle a t arbitrairement xe 819x1024


pixels :
184

QUAND LE CONTENU DPASSE LA TAILLE DU CONTRLE, DE LA VUE OU


DE LA FENTRE

[ scrollView setContentSize : CGSizeMake ( 819 , 1024 ) ];

Pour que la zone d'achage du contrle Scroll View s'adapte exactement celle de
l'image, vous pouvez utiliser l'instruction suivante :
1

[ scrollView setContentSize : CGSizeMake ( imageView . image . size .


width , imageView . image . size . height ) ];

Si vous optez pour une adaptation automatique de la taille du Scroll View,


pensez dnir l'outlet imageView pour le contrle Image View, sans quoi
une erreur apparatra dans Xcode sur cette nouvelle ligne.

Voici le code complet, que vous pouvez tlcharger grce un code web.
ViewController.h
1
2
3
4
5
6
7

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
@property ( weak , nonatomic ) IBOutlet UIScrollView * scrollView ;
@property ( weak , nonatomic ) IBOutlet UIImageView * imageView ;
@end

ViewController.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# import " ViewController . h "


@implementation ViewController
@synthesize scrollView ;
@synthesize imageView ;
- ( void ) didReceiveMemoryWarning
{
[ super didReceiveMemoryWarning ];
// Release any cached data , images , etc that aren 't in use .
}
# pragma mark - View lifecycle
- ( void ) viewDidLoad
{
[ super viewDidLoad ];
[ scrollView setScrollEnabled : YES ];
// [ scrollView setContentSize : CGSizeMake ( 819 , 1024 ) ];
[ scrollView setContentSize : CGSizeMake ( imageView . image . size .
width , imageView . image . size . height ) ];
}

185

CHAPITRE 11.

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

LES CONTRLES QUI AFFICHENT DES DONNES (2/2)

- ( void ) viewDidUnload
{
[ self setScrollView : nil ];
[ self setImageView : 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

Copier ce code
B
Code web : 547909

Demander son avis l'utilisateur


Il est parfois utile d'acher une bote de dialogue modale (c'est--dire qui se superpose
la fentre de l'application et qui y interdit toute action) pour demander l'utilisateur de prendre une dcision. Par exemple, pour conrmer l'arrt de l'application ou
l'crasement d'un chier. Deux classes peuvent tre utilises cet eet : UIAlertView
186

DEMANDER SON AVIS L'UTILISATEUR

et UIActionSheet.

Une bote de dialogue modale avec un contrle UIAlertView


Dnissez un projet bas sur le modle Single View Application et donnez-lui le
nom  alerte . Dans le volet de navigation, cliquez sur MainStoryboard.storyboard
et ajoutez un contrle Label la vue. Double-cliquez dans le Label et tapez  Cliquez
sur un bouton . Dnissez un outlet pour le Label et donnez-lui le nom status.
Vous allez maintenant ajouter quelques lignes de code dans la mthode viewDidLoad
pour provoquer l'achage de la bote de dialogue modale. Cliquez sur ViewController.m
dans le volet de navigation et compltez la mthode viewDidLoad comme suit :
1
2
3
4
5
6
7
8
9
10

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
UIAlertView * alert = [[ UIAlertView alloc ]
initWithTitle : @ " Voulez - vous arr ter ? "
message : @ " Confirmez que vous voulez quitter l ' application "
delegate : self
cancelButtonTitle : @ " Annuler " otherButtonTitles : nil ];
[ alert addButtonWithTitle : @ " Confirmer " ];
[ alert show ];
}

Les lignes 4 7 dnissent l'objet alert de type UIAlertView.


Cet objet est initialis avec :
 un titre : initWithTitle:@"Voulez-vous arrter ?" ;
 un message : message:@"Confirmez que vous voulez quitter l'application" ;
 un bouton Annuler : cancelButtonTitle:@"Annuler".
Les vnements qui lui sont lis sont traits dans la classe alertViewController ellemme (delegate:self).
L'instruction suivante ajoute le bouton Confirmer la bote de dialogue :
1

[ alert addButtonWithTitle : @ " Confirmer " ];

Enn, la dernire instruction ache la bote de dialogue :


1

[ alert show ];

Vous pouvez lancer l'application et voir qu'elle fonctionne la perfection (gure 11.7),
si ce n'est que les boutons ne produisent aucun eet.
Nous allons rgler ce problme en dnissant une mthode action. Ajoutez le code
suivant au chier alertViewController.m :
1
2

- ( void ) alertView :( UIAlertView *) alertView


didDismissWithButtonIndex :( NSInteger ) buttonIndex {
if ( buttonIndex == 0 )

187

CHAPITRE 11.

LES CONTRLES QUI AFFICHENT DES DONNES (2/2)

Figure 11.7  Notre application se lance. . . mais les boutons ne produisent aucun eet
3
4
5
6

else
}

status . text = @ " Vous avez cliqu sur Annuler " ;


status . text = @ " Vous avez cliqu sur Confirmer " ;

La mthode alertView:didDismissWithButtonIndex est excute lorsque l'utilisateur clique sur un des boutons de la bote de dialogue modale. L'entier buttonIndex
reprsente l'index du bouton cliqu. Il vaut :
 0 si le bouton Annuler a t cliqu ;
 1 si le bouton Confirmer a t cliqu.
En fonction du bouton cliqu, un message ou un autre est ach dans le contrle Label.
Voici le code de l'application.
ViewController.h
1
2
3
4
5
6

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
@property ( weak , nonatomic ) IBOutlet UILabel * status ;
@end

188

DEMANDER SON AVIS L'UTILISATEUR

ViewController.m
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

# import " ViewController . h "


@implementation ViewController
@synthesize status ;
- ( void ) didReceiveMemoryWarning
{
[ super didReceiveMemoryWarning ];
// Release any cached data , images , etc that aren 't in use .
}
# pragma mark - View lifecycle
- ( void ) viewDidLoad
{
[ super viewDidLoad ];
UIAlertView * alert = [[ UIAlertView alloc ]
initWithTitle : @ " Voulez - vous arr ter ? "
message : @ " Confirmez que vous voulez quitter l ' application "
delegate : self
cancelButtonTitle : @ " Annuler " otherButtonTitles : nil ];
[ alert addButtonWithTitle : @ " Confirmer " ];
[ alert show ];
}
- ( void ) alertView :( UIAlertView *) alertView
didDismissWithButtonIndex :( NSInteger ) buttonIndex {
if ( buttonIndex == 0 )
status . text = @ " Vous avez cliqu sur Annuler " ;
else
status . text = @ " Vous avez cliqu sur Confirmer " ;
}
- ( void ) viewDidUnload
{
[ self setStatus : 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
{

189

CHAPITRE 11.

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

LES CONTRLES QUI AFFICHENT DES DONNES (2/2)

[ 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

Copier ce code
B
Code web : 584901


Une bote de dialogue modale avec un contrle UIActionSheet
Une variante du contrle UIAlertView consiste utiliser le contrle UIActionSheet.
Ce dernier ache une vue modale qui se superpose la vue actuelle dans la partie
infrieure de la fentre.
Dnissez un projet bas sur le modle Single View Application et donnez-lui le nom
 actionSheet . Dans le volet de navigation, cliquez sur MainStoryboard.storyboard
et ajoutez un contrle Label la vue. Double-cliquez sur le Label et tapez  Appuyez
sur un bouton . Enn, dnissez un outlet pour ce Label et donnez-lui le nom status.
Vous allez maintenant ajouter quelques lignes de code dans la mthode viewDidLoad
pour provoquer l'achage de la vue modale. Cliquez sur ViewController.m dans le
volet de navigation, et compltez la mthode viewDidLoad comme suit :
1
2
3
4
5
6
7
8

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
UIActionSheet * actionSheet = [[ UIActionSheet alloc ]
initWithTitle : @ " Voulez - vous arr ter l ' application ? "
delegate : self cancelButtonTitle : nil destructiveButtonTitle :
nil
otherButtonTitles : @" Oui " , @ " Non " ,@ " Je ne sais pas " , nil ];
actionSheet . actionSheetStyle = UIActionSheetStyleBlackOpaque ;
actionSheet . destructiveButtonIndex = 1 ;

190

DEMANDER SON AVIS L'UTILISATEUR

9
10

[ actionSheet showInView : self . view ];

La premire instruction dnit l'objet actionSheet de type UIActionSheet.


Cet objet est initialis avec :
 un titre : initWithTitle:@"Voulez-vous arrter l'application ?" ;
 trois boutons : otherButtonTitles:@"Oui", @"Non",@"Je ne sais pas", nil).
Le traitement du contrle se fait dans la classe actionSheetViewController ellemme : delegate:self.
L'instruction suivante dnit le style du contrle :
1

actionSheet . actionSheetStyle = UIActionSheetStyleBlackOpaque ;

Les valeurs possibles pour la proprit actionSheetStyle sont les suivantes 1 :


 UIActionSheetStyleAutomatic ;
 UIActionSheetStyleDefault ;
 UIActionSheetStyleBlackTranslucent ;
 UIActionSheetStyleBlackOpaque.
L'instruction suivante indique que le bouton d'index 1 (le deuxime en d'autres termes)
doit tre direnci des autres, car il prsente un caractre particulier. Ce bouton
apparat en rouge.
1

actionSheet . destructiveButtonIndex = 1 ;

Dans cet exemple, le bouton n'a rien de particulier. Mais imaginez par contre
que vous demandiez l'utilisateur de supprimer une table de scores dans un
jeu ou d'eacer un chier. Un tel bouton pourrait alors tre trs utile !

L'instruction suivante ajoute la vue modale dans la vue courante :


1

[ actionSheet showInView : self . view ];

Lancez l'application dans le simulateur. Vous devriez obtenir quelque chose ressemblant
la gure 11.8.
L'application fonctionne, mais un triangle de couleur jaune apparat dans le
code, comme la gure 11.9. Est-ce que j'aurais rat quelque chose ?

Observez d'un peu plus prs le message d'erreur. Xcode nous indique que la classe
ViewController n'implmente pas le protocole UIActionSheetDelegate et ne peut
donc pas rpondre aux vnements gnrs par l'objet actionSheet. Qu' cela ne
tienne : cliquez sur ViewController.h dans le volet de navigation et ajoutez le protocole demand dans la dclaration de l'interface :
1. N'hsitez pas les tester !

191

CHAPITRE 11.

LES CONTRLES QUI AFFICHENT DES DONNES (2/2)

Figure 11.8  L'application lance dans le simulateur

Figure 11.9  Xcode ache un triangle de couleur jaune

192

DEMANDER SON AVIS L'UTILISATEUR

1
2
3
4
5
6

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController <
UIActionSheetDelegate >
@property ( weak , nonatomic ) IBOutlet UILabel * status ;
@end

Le problme a disparu, comme par magie.


Maintenant, il ne reste plus qu' dnir le code qui ragit aux clics sur les boutons de la
bote de dialogue modale. Cliquez sur ViewController.m dans le volet de navigation
et ajoutez la mthode actionSheet:clickedButtonAtIndex dans le code :
1
2
3
4
5
6
7
8
9

- ( void ) actionSheet :( UIActionSheet *) actionSheet


clickedButtonAtIndex :( NSInteger ) buttonIndex
{
if ( buttonIndex == 0 )
status . text = @ " Vous avez cliqu sur Oui " ;
if ( buttonIndex == 1 )
status . text = @ " Vous avez cliqu sur Non " ;
if ( buttonIndex == 2 )
status . text = @ " Vous avez cliqu sur Je ne sais pas " ;
}

Cette mthode est appele lorsqu'un bouton de la bote de dialogue modale est press.
Le NSInteger buttonIndex reprsente l'index du bouton press par l'utilisateur (0 si
le premier bouton est press, 1 si le deuxime bouton est press, etc.).
La mthode clickedButtonAtIndex se contente d'acher un texte en rapport avec le
bouton cliqu dans le contrle Label.
Vous trouverez la suite le code de l'application.
ViewController.h
1
2
3
4
5
6

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController <
UIActionSheetDelegate >
@property ( weak , nonatomic ) IBOutlet UILabel * status ;
@end

ViewController.m
1
2
3
4
5

# import " ViewController . h "


@implementation ViewController
@synthesize status ;

193

CHAPITRE 11.

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

LES CONTRLES QUI AFFICHENT DES DONNES (2/2)

- ( void ) didReceiveMemoryWarning
{
[ super didReceiveMemoryWarning ];
// Release any cached data , images , etc that aren 't in use .
}
# pragma mark - View lifecycle
- ( void ) viewDidLoad
{
[ super viewDidLoad ];
UIActionSheet * actionSheet = [[ UIActionSheet alloc ]
initWithTitle : @ " Voulez - vous arr ter l ' application ? "
delegate : self cancelButtonTitle : nil destructiveButtonTitle :
nil
otherButtonTitles : @" Oui " , @ " Non " ,@ " Je ne sais pas " , nil ];
actionSheet . actionSheetStyle = UIActionSheetStyleBlackOpaque ;
actionSheet . destructiveButtonIndex = 1 ;
[ actionSheet showInView : self . view ];
}
- ( void ) actionSheet :( UIActionSheet *) actionSheet
clickedButtonAtIndex :( NSInteger ) buttonIndex
{
if ( buttonIndex == 0 )
status . text = @ " Vous avez cliqu sur Oui " ;
if ( buttonIndex == 1 )
status . text = @ " Vous avez cliqu sur Non " ;
if ( buttonIndex == 2 )
status . text = @ " Vous avez cliqu sur Je ne sais pas " ;
}
- ( void ) viewDidUnload
{
[ self setStatus : 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 ];
}

194

DEMANDER SON AVIS L'UTILISATEUR

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

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

Copier ce code
Code web : 194709

En rsum

 Le contrle Map View permet d'acher une carte, comme dans l'application Maps
d'Apple. En utilisant les mthodes de la classe MKMapView, vous pouvez, entre autres,
centrer la carte sur une coordonne spcique, choisir la taille de la zone acher
ou encore ajouter des informations personnalises sur la carte.
 Vous utiliserez un contrle Scroll View pour acher un contenu qui est plus grand
que la fentre de l'application. Les utilisateurs pourront alors faire glisser la fentre
de visualisation sur le contenu, mais aussi zoomer vers l'avant et vers l'arrire en
pinant/tirant l'cran avec deux doigts.
 Il est parfois utile d'acher une bote de dialogue modale (c'est--dire qui se superpose la fentre de l'application et qui y interdit toute action) pour demander
l'utilisateur de prendre une dcision. Par exemple, pour conrmer l'arrt de l'application ou l'crasement d'un chier. Deux classes peuvent tre utilises cet eet :
UIAlertView et UIActionSheet.

195

CHAPITRE 11.

196

LES CONTRLES QUI AFFICHENT DES DONNES (2/2)

Chapitre

12

Les informations tabulaires


Dicult :

es applications iOS ont souvent recours des vues tabulaires pour prsenter des listes
de donnes. Ces listes permettent de :
 prsenter un ensemble d'options slectionnables par l'utilisateur ;
 naviguer dans un ensemble de donnes structures hirarchiquement ;
 prsenter une liste d'lments tris selon un ou plusieurs critres ;
 dnir plusieurs niveaux de dtail pour faciliter l'achage des informations sur des devices
de petite taille.
Ce chapitre va s'intresser aux trois types de vues tabulaires utilisables sur un device : Table
View, Picker View et Date Picker. Il va vous montrer comment acher des contrles
tabulaires dans vos applications, comment les remplir et comment ragir aux actions des
utilisateurs.

197

CHAPITRE 12.

LES INFORMATIONS TABULAIRES

Xcode propose trois contrles pour manipuler des informations tabulaires : Table View,
Picker View et Date Picker :
 le premier ache des listes d'informations sur une colonne ;
 le deuxime ache des informations sur une ou plusieurs colonnes, sous la forme
d'une roulette 3D ;
 le troisime est trs similaire au deuxime, ceci prs qu'il est spcialis dans l'achage des dates et d'heures.
Nous allons voir comment les utiliser dans ce chapitre.

Listes d'informations sur une colonne


Les contrles Table View sont utiliss pour acher des listes d'informations sur une
colonne. Plusieurs applications fournies avec votre device utilisent un contrle Table
View (gure 12.1).

Figure 12.1  L'application Contacts utilise un Table

View

Les contrles Table View peuvent tre composs de zro (mme si cela n'ore pas
beaucoup d'intrt), une ou plusieurs sections. Chaque section peut :
 comporter zro, une ou plusieurs lignes ;
 tre prcde d'un en-tte de section ;
 tre suivie d'un pied de section.
Les sections sont identies par leur numro d'index dans le tableau : premire section,
198

LISTES D'INFORMATIONS SUR UNE COLONNE

deuxime section, etc. Les lignes sont identies par leur numro d'index dans une
section : premire ligne de la premire section, deuxime ligne de la premire section,
etc.
L'utilisateur peut se dplacer verticalement dans un contrle Table View en utilisant
une gestuelle de glisser. Lorsqu'il clique sur un des lments lists, une vue dtaille
de cet lment est ache. La communication entre le contrle Table View et les
direntes vues dtailles se fait via un contrle Table View Controller.

Premire approche
Pour faciliter l'criture d'une application base sur l'utilisation d'un Table View et des
vues dtailles correspondantes, le plus simple consiste utiliser le modle Master-Detail
Application.
Crez un nouveau projet bas sur le modle Master-Detail Application, cliquez
sur Next, donnez le nom  tableView  l'application, choisissez le dossier de sauvegarde et validez en cliquant sur Create. Une fois l'application cre, cliquez sur
MainStoryboard.storyboard dans le volet de navigation. Comme vous pouvez le voir
la gure 12.2, un contrleur de navigation, un contrle Table View et une vue dtaille ont t insrs dans l'application.

Figure 12.2  Un contrleur de navigation, un contrle Table

ont t insrs dans l'application

View et une vue dtaille

Excutez l'application en cliquant sur Run. Le contrle Table View est bien visible,
mais il ne contient aucune donne. Nous allons remdier cette situation en dnissant
quelques donnes textuelles et en les reliant au contrle Table View.
La source de donnes peut provenir d' peu prs n'importe o : d'un tableau, d'un
chier XML ou d'une base de donnes par exemple. Pour que les choses soient aussi
simples que possible, nous allons utiliser un tableau comme source de donnes. Cliquez sur MasterViewController.h dans le volet de navigation et dnissez l'objet
NSMutableArray *maListe :
199

CHAPITRE 12.

1
2
3
4
5
6
7
8

LES INFORMATIONS TABULAIRES

# import < UIKit / UIKit .h >


@interface MasterViewController : UITableViewController
{
NSMutableArray * maListe ;
}
@end

Maintenant, cliquez sur MasterViewController.m dans le volet de navigation. Pour


que le tableau soit rempli ds le dmarrage de l'application, nous allons ajouter quelques
instructions dans la mthode viewDidLoad :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
maListe = [ NSMutableArray array ];
[ maListe addObject : @ " Paris " ];
[ maListe addObject : @ " Lyon " ];
[ maListe addObject : @ " Marseille " ];
[ maListe addObject : @ " Toulouse " ];
[ maListe addObject : @ " Nantes " ];
[ maListe addObject : @ " Nice " ];
[ maListe addObject : @ " Bordeaux " ];
[ maListe addObject : @ " Montpellier " ];
[ maListe addObject : @ " Rennes " ];
[ maListe addObject : @ " Lille " ];
[ maListe addObject : @ " Le Havre " ];
[ maListe addObject : @ " Reims " ];
[ maListe addObject : @ " Le Mans " ];
[ maListe addObject : @ " Dijon " ];
[ maListe addObject : @ " Grenoble " ];
[ maListe addObject : @ " Brest " ];
self . navigationItem . title = @ " Grandes villes " ;
}

Copier ce code
B
Code web : 348581


L'instruction de la ligne 4 initialise l'objet maListe :
maListe = [ NSMutableArray array ];

Les instructions suivantes ajoutent des lments dans maListe en appliquant la mthode addObject l'objet maListe. Par exemple :
1

[ maListe addObject : @ " Paris " ];

Enn, la ligne 21 dnit le titre qui sera ach sur la premire ligne du contrle Table
View :
1

self . navigationItem . title = @ " Grandes villes " ;

200

LISTES D'INFORMATIONS SUR UNE COLONNE

Je sens que vous brlez d'impatience de voir ces donnes aches dans le Table View.
Allez, cliquez sur Run.
...
Oh consternation ! Le contrle Table View est toujours vide ! Rchissez un peu. Tout
ce qui a t fait jusqu'ici, c'est de crer un objet NSMutableArray. Comment le contrle
Table View pourrait-il supposer qu'il doit l'utiliser comme source de donnes ?
Pour cela, deux actions doivent tre accomplies. Vous devez :
1. indiquer au contrle Table View combien de donnes il doit acher ;
2. relier les objets Table View et maListe.
Pour connatre le nombre d'lments du tableau maListe, vous utiliserez l'instruction
suivante :
1

[ maListe count ];

La mthode prdnie numberOfRowsInSection retourne un entier qui correspond


au nombre d'lments acher dans le Table View. Par dfaut, la valeur retourne est gale 0 : aucune information n'est donc ache. En remplaant le 0 la
suite de l'instruction return par le message [maListe count], le contrle Table View
sait combien d'lments il doit acher. Dnissez la mthode suivante dans le chier
MasterViewController.m :
1
2
3
4

- ( NSInteger ) tableView :( UITableView *) tableView


numberOfRowsInSection :( NSInteger ) section
{
return [ maListe count ];
}

Il ne reste plus qu' relier le Table View au contrle maListe. Cette tape se fera grce
la mthode cellForRowAtIndexPath. Consultez la documentation Apple pour avoir
une ide du contenu de cette mthode (gure 12.3).
Les premires lignes (1) dnissent un objet cell de classe UITableViewCell et le
relient une cellule du Table View. Nous les reprendrons telles quelles.
Les dernires lignes (2) sont propres l'exemple pris par Apple, nous allons donc les
modier. Dans le cas qui nous proccupe, les cellules (cell.textLabel.text) doivent
tre relies aux lments du Table View ([maListe objectAtIndex: ...]) dont l'index correspond au numro de ligne du Table View (indexPath.row). Voici le code
complet de la mthode cellForRowAtIndexPath :
1
2
3
4
5
6

- ( UITableViewCell *) tableView :( UITableView *) tableView


cellForRowAtIndexPath :( NSIndexPath *) indexPath
{
static NSString * MyIdentifier = @ " MyIdentifier " ;
UITableViewCell * cell = [ tableView
dequeueReusableCellWithIdentifier : MyIdentifier ];

201

CHAPITRE 12.

LES INFORMATIONS TABULAIRES

Figure 12.3  La documentation

202

LISTES D'INFORMATIONS SUR UNE COLONNE

if ( cell == nil )
cell = [[ UITableViewCell alloc ] initWithStyle :
UITableViewCellStyleDefault reuseIdentifier : MyIdentifier
];

7
8
9
10
11
12
13
14

// Configuration de la cellule
NSString * cellValue = [ maListe objectAtIndex : indexPath . row ];
cell . textLabel . text = cellValue ;
return cell ;

Copier ce code
B
Code web : 553565


Les lignes 1 8 ainsi que la ligne 13 sont issues de l'aide Apple. La ligne 11 dnit
l'objet cellValue de classe NSString (NSString *cellValue) et y stocke l'lment du
tableau maListe ([maListe ...) qui se trouve la ligne (objectAtIndex) courante
(indexPath.row]).
1

NSString * cellValue = [ maListe objectAtIndex : indexPath . row ];

La ligne 12 aecte la valeur obtenue la ligne prcdente la cellule :


1

cell . textLabel . text = cellValue ;

Avant de cliquer sur Run, vous devez encore dire Xcode que les donnes acher
dans le Table View seront dnies dans l'application. Comme la gure 12.4, cliquez
sur MainStoryboard.storyboard dans le volet de navigation (1), cliquez sur Table
View dans la zone d'dition (2), sur l'icne Hide or show the Utilities (3) puis sur
l'icne Show the Attributes inspector (4). Choisissez enn Dynamic Prototypes
dans la liste droulante Content (5).
Maintenant, vous pouvez cliquer sur Run. La fentre du simulateur iOS devrait acher
quelque chose ressemblant la gure 12.5.
Une dernire petite chose. Avez-vous remarqu le point d'exclamation dans la partie
suprieure de la fentre de Xcode ? Si vous cliquez dessus, un message d'erreur vous
indique ce qui ne va pas. Ce dernier indique  Prototype table cells must have reuse
identiers , soit en bon franais  Le prototype des cellules du tableau doit avoir un
identiant .
Comme indiqu la gure 12.6, cliquez sur le prototype des cellules dans la vue Master
(1), sur l'icne Show the Attributes inspector dans le volet des utilitaires (2), puis
dnissez un identiant dans la zone de texte Identifier (3).

203

CHAPITRE 12.

LES INFORMATIONS TABULAIRES

Figure 12.4  Les donnes doivent tre dnies dans l'application

Figure 12.5  Les donnes apparaissent dans l'application

204

LISTES D'INFORMATIONS SUR UNE COLONNE

Figure 12.6  Dnissez un identiant dans la zone de texte Identifier

Utilisation de la vue dtaille


Les contrles Table View sont gnralement utiliss avec une vue secondaire qui donne
des dtails sur l'lment slectionn par l'utilisateur dans la liste. Nous allons voir
comment utiliser cette vue dans l'application prcdente. Rappelez-vous : lors de la
cration de l'application tableView, une vue dtaille a t ajoute au canevas (gure
12.7). Reste donc voir comment l'utiliser.
En observant cette gure, je vois que la vue Master n'est pas relie la vue
Detail. Et pourtant, elle l'tait tout l'heure. Que s'est-il pass ?

Eectivement, ces deux vues taient relies, mais lorsque vous avez slectionn Dynamic
dans la proprit Content de la vue Master, le lien a t bris. Qu' cela
ne tienne, nous allons le recrer !
Si ce n'est pas dj fait, achez le canevas en cliquant sur MainStoryboard.storyboard
dans le volet de navigation. Ensuite, comme indiqu la gure 12.8, cliquez sur l'lment qui reprsente une cellule dans la vue Master (1) puis contrle-glissez-dposez
cet lment sur la vue Detail (2). Au relchement du bouton gauche de la souris,
slectionnez Push dans le menu (3).
Prototypes

205

CHAPITRE 12.

LES INFORMATIONS TABULAIRES

Figure 12.7  Une vue dtaille a t ajoute au canevas

Figure 12.8  Il faut relier la vue Master la vue Detail

206

LISTES D'INFORMATIONS SUR UNE COLONNE

La liaison entre les vues Master et Detail est maintenant rtablie (gure 12.9).

Figure 12.9  La liaison entre les vues Master et Detail est maintenant rtablie

Pour pouvoir y faire rfrence dans le code, vous allez lui donner un nom. Comme
indiqu sur la gure 12.10, cliquez sur le symbole qui identie la liaison dans le canevas (1), sur l'icne Hide or show the Utilities dans la barre d'outils (2), sur
Show the Attributes inspector dans le volet des utilitaires (3) puis donnez le nom
 detailSegue  la liaison (4).

Figure 12.10  Il faut donner un nom la liaison pour pouvoir y faire rfrence

Vous allez maintenant insrer un contrle Label dans la vue Detail. Ce contrle sera
207

CHAPITRE 12.

LES INFORMATIONS TABULAIRES

utilis pour acher des informations en relation avec l'lment slectionn par l'utilisateur dans la vue Master.
Une fois le contrle Label insr dans la vue Detail, associez-lui l'outlet donneeRecue
pour qu'il soit accessible dans le code.
Je pense que cette opration doit maintenant tre habituelle pour vous, mais tout
hasard, je vais faire un rappel. Pour dnir l'outlet unMessage pour le contrle Label :
1. dans la barre d'outils de Xcode, au-dessus du libell Editor, cliquez sur l'icne
Show the Assistant editor ;
2. contrle-glissez-dposez le contrle Label dans le chier d'en-ttes, juste audessus du @end nal ;
3. au relchement du bouton gauche de la souris, donnez le nom  donneeRecue 
l'outlet et validez en cliquant sur Connect.
Le code du chier d'en-ttes doit maintenant ressembler ceci :
1
2
3
4
5
6
7
8
9

# import < UIKit / UIKit .h >


@interface DetailViewController : UIViewController
@property ( strong , nonatomic ) id detailItem ;
@property ( strong , nonatomic ) IBOutlet UILabel *
detailDescriptionLabel ;
@property ( weak , nonatomic ) IBOutlet UILabel * donneeRecue ;
@end

Lorsque l'utilisateur slectionne un lment dans le contrle Table View, la vue Detail
remplace la vue Master. Pour passer des informations de la vue Master la vue Detail,
Apple prconise d'utiliser la mthode prepareForSegue. Malheureusement, il n'est pas
possible d'atteindre directement le label donneeRecue, vous devez passer par une variable intermdiaire. Cliquez sur DetailViewController.h dans le volet de navigation
et dnissez la proprit texteAAfficher comme suit :
@property ( strong , nonatomic ) id texteAAfficher ;

Le chier
vantes :
1
2
3
4
5
6
7
8
9

DetailViewController.h

doit maintenant contenir les instructions sui-

# import < UIKit / UIKit .h >


@interface DetailViewController : UIViewController
@property ( strong , nonatomic ) id texteAAfficher ;
@property ( strong , nonatomic ) id detailItem ;
@property ( strong , nonatomic ) IBOutlet UILabel *
detailDescriptionLabel ;
@property ( weak , nonatomic ) IBOutlet UILabel * donneeRecue ;
@end

208

LISTES D'INFORMATIONS SUR UNE COLONNE

Cliquez sur DetailViewController.m dans le volet de navigation et ajoutez une instruction synthesize pour pouvoir accder la proprit texteAAfficher :
1

@synthesize texteAAfficher = _texteAAfficher ;

a y est, tout est en place pour insrer la mthode prepareForSegue. Cliquez sur
MasterViewController.m dans le volet de navigation et insrez les instructions suivantes dans le code (peu importe l'endroit) :
1
2
3
4
5
6
7
8

-( void ) prepareForSegue :( UIStoryboardSegue *) segue sender :( id )


sender {
if ([[ segue identifier ] isEqualToString : @" detailSegue " ])
{
NSInteger selectedIndex = [[ self . tableView
indexPathForSelectedRow ] row ];
DetailViewController * dvc = [ segue
destinationViewController ];
dvc . texteAAfficher = [ NSString stringWithFormat : @ " % @ " , [
maListe objectAtIndex : selectedIndex ]];
}
}

Ne soyez pas impressionns par l'apparente complexit du code : l'autocompltion est


votre amie. Ainsi par exemple, lorsque vous commencez crire les premires lettres
de la mthode prepareForSegue, une bulle
 s'ache sur l'cran, comme la gure
12.11. Appuyez simplement sur la touche Entre pour recopier le texte propos par
l'autocompltion.
Figure 12.11  Xcode propose l'autocompltion

La ligne 2 teste si l'identiant de la transition entre la vue Master et la vue Detail a


bien pour nom  detailSegue  :
1

if ([[ segue identifier ] isEqualToString : @" detailSegue " ])

Rappelez-vous, ce nom a t dni un peu plus tt. Et maintenant, vous


l'utilisez dans le code.

La ligne 4 dnit le NSInteger selectedIndex et l'initialise avec l'index de la cellule


choisie par l'utilisateur (indexPathForSelectedRow) du contrle TableView de la vue
Master (self.tableView) :
1

NSInteger selectedIndex = [[ self . tableView


indexPathForSelectedRow ] row ];

vaudra 0 si l'utilisateur a choisi le premier lment. Il vaudra 1 s'il a


choisi le deuxime lment. Ainsi de suite. . .

selectedIndex

209

CHAPITRE 12.

LES INFORMATIONS TABULAIRES

Maintenant, nous connaissons l'index de la cellule choisie par l'utilisateur. Encore fautil accder au Label de la vue Detail. Pour cela, la ligne 5 dnit l'objet dvc de classe
DetailViewController (DetailViewController *dvc) et l'initialise avec la vue qui
va tre ache ([segue destinationViewController]) :
DetailViewController * dvc = [ segue destinationViewController ];

Il ne reste plus qu' aecter le contenu de la cellule la proprit texteAAfficher.


C'est prcisment ce que fait la ligne 6. La proprit texteAAfficher est initialise
avec l'lment du tableau maListe d'index selectedIndex. Cet objet est converti en
un NSString avant d'tre stock dans la proprit texteAAfficher :
1

dvc . texteAAfficher = [ NSString stringWithFormat : @ " % @ " , [ maListe


objectAtIndex : selectedIndex ]];

Mais au fait, comment le code de la vue Master va-t-il pouvoir accder au


code de la vue Detail ?

Vous devez ajouter une instruction import au dbut du chier MasterViewController.m,


sans quoi Master n'arrivera pas  dialoguer  avec Detail et plusieurs erreurs apparatront dans le code :
1

# import " DetailViewController . h "

Aprs tous ces eorts, vous devez certainement tre impatients de lancer l'application.
Vous pouvez toujours le faire, mais je suis assez pessimiste quant au rsultat obtenu : il
est vrai que la vue Master a indiqu la vue Detail quelle tait la cellule slectionne
par l'utilisateur. Mais rappelez-vous, cette indication a t fournie dans la proprit
texteAAfficher et non dans le Label donneeRecue. Vous allez donc devoir agir sur
le code de la vue Detail. Cliquez sur DetailViewController.m et ajoutez la ligne 6
la mthode viewDidLoad :
1
2
3
4
5
6
7

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
// Do any additional setup after loading the view , typically
from a nib .
[ self configureView ];
_donneeRecue . text = _texteAAfficher ;
}

Cette ligne recopie simplement le contenu de la proprit texteAAfficher dans le


Label.
a y est, vous pouvez lancer l'application et proter du passage de donnes entre les
vues Master et Detail. La gure 12.12 reprsente par exemple ce que vous devriez
obtenir si vous choisissez  Toulouse  dans la vue Master.
Le code web suivant vous permet de copier les codes de l'application.
210

LISTES D'INFORMATIONS SUR UNE OU PLUSIEURS COLONNES

Figure 12.12   Toulouse  est slectionn dans la vue Master


Copier ce code
B
Code web : 170881

Listes d'informations sur une ou plusieurs colonnes


Les contrles Table View ont une variante : les Picker View. Outre leur aspect  roulette 3D , ces contrles peuvent acher des informations sur une ou plusieurs colonnes,
et chaque colonne peut comporter un nombre d'informations dirent.
Pour eectuer une slection, l'utilisateur tourne la ou les roues (gure 12.13) jusqu'
ce que la ou les valeurs aches se trouvent sous la marque de slection. Les valeurs
slectionnes sont obtenues avec la mthode pickerView:didSelectRow:inComponent.

Figure 12.13  L'utilisateur utilise des  roulettes 3D  pour faire une slection

Ces contrles relvent de la classe UIPickerView. Pour illustrer leur fonctionnement,


nous allons dnir une application dans laquelle l'utilisateur pourra slectionner une
211

CHAPITRE 12.

LES INFORMATIONS TABULAIRES

entre dans un contrle Picker View. Cette dernire sera alors ache dans un contrle
Label.
Dnissez une nouvelle application base sur le modle Single View Application et
donnez-lui le nom  picker . En utilisant Interface Builder, ajoutez un contrle Picker
View et un contrle Label au chier MainStoryboard.storyboard. Double-cliquez sur
le contrle Label et tapez  Choisissez une ville . L'interface de l'application doit
maintenant ressembler la gure 12.14.

Figure 12.14  L'interface de l'application

Reliez les deux contrles de l'interface au code en les contrle-glissant-dposant depuis


la zone d'dition dans le chier ViewController.h. Dnissez un outlet pour le contrle
Picker View et donnez-lui le nom pv. Dnissez un outlet pour le contrle Label et
donnez-lui le nom status. Le chier ViewController.h doit maintenant ressembler
ceci :
1
2
3
4
5
6
7

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
@property ( weak , nonatomic ) IBOutlet UIView * pv ;
@property ( weak , nonatomic ) IBOutlet UILabel * status ;
@end

212

LISTES D'INFORMATIONS SUR UNE OU PLUSIEURS COLONNES

Pour utiliser un contrle Picker View, il est ncessaire d'implmenter les protocoles
UIPickerViewDelegate (traitement des actions de l'utilisateur dans le Picker View)
et UIPickerViewDataSource (donnes utilises dans le Picker View).
Mais au fait, qu'est-ce que a veut dire  implmenter un protocole  ? J'ai
un trou de mmoire !

Dans le jargon Objective-C, un protocole consiste en une liste de dclarations de mthodes. Lorsqu'une classe implmente un protocole, cela signie qu'elle peut appeler
les mthodes qui sont dnies dans ce protocole. Supposons par exemple que la classe
Voiture, sous-classe de Vehicule, implmente le protocole Moteur. Pour le signier
Xcode, vous devrez modier l'instruction @interface.
1
2
3

@interface Voiture : Vehicule {


...
}

Comme ceci :
1
2
3

@interface Voiture : Vehicule < Moteur >{


...
}

Ici, la classe ViewController, sous-classe de UIViewController, doit implmenter


les protocoles UIPickerViewDelegate et UIPickerViewDataSource. La dclaration
de l'interface :
1
2
3

@interface ViewController : UIViewController {


...
}

doit donc tre modie comme suit :


1
2
3

@interface ViewController : UIViewController <


UIPickerViewDelegate , UIPickerViewDataSource > {
...
}

Si ceci n'est pas clair, relisez calmement les quelques phrases qui prcdent. Vous verrez,
il n'y a rien de sorcier !
Les donnes aches dans le contrle Picker View vont tre stockes dans un tableau
que nous appellerons maListe. Vous devez dnir ce tableau dans le chier d'en-ttes,
qui devrait maintenant ressembler ceci :
1
2
3
4
5

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController <
UIPickerViewDelegate , UIPickerViewDataSource >
{
NSMutableArray * maListe ;

213

CHAPITRE 12.

6
7
8
9
10
11

LES INFORMATIONS TABULAIRES

}
@property ( weak , nonatomic ) IBOutlet UIView * pv ;
@property ( weak , nonatomic ) IBOutlet UILabel * status ;
@end

L'alimentation et la gestion du contrle Picker View seront ralises dans le code de


l'application (ViewController.m). Pour l'indiquer Xcode, il sut de relier les outlets
dataSource et delegate du Picker View au File's Owner (gure 12.15).
1. Cliquez sur MainStoryboard.storyboard dans le volet de navigation (1).
2. Cliquez sur le contrle Picker View dans le volet de navigation (2).
3. Achez le volet des utilitaires en cliquant sur l'icne Hide or show the Utilities
(3).
4. Cliquez sur Show the Connections inspector dans le volet des utilitaires (4).
5. Sous Outlets, reliez le cercle qui se trouve droite de dataSource l'icne View
Controller (5).
6. Toujours sous Outlets, reliez le cercle qui se trouve droite de delegate l'icne
View Controller (6).

Figure 12.15  Il faut relier les outlets dataSource et delegate du Picker

File's Owner

View

au

Il est temps de modier le chier .m. Cliquez sur ViewController.m dans le volet de
navigation.
214

LISTES D'INFORMATIONS SUR UNE OU PLUSIEURS COLONNES

Le tableau sera initialis dans la mthode viewDidLoad :


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
maListe = [[ NSMutableArray alloc ] init ];
[ maListe addObject : @ " Paris " ];
[ maListe addObject : @ " Lyon " ];
[ maListe addObject : @ " Marseille " ];
[ maListe addObject : @ " Toulouse " ];
[ maListe addObject : @ " Nantes " ];
[ maListe addObject : @ " Nice " ];
[ maListe addObject : @ " Bordeaux " ];
[ maListe addObject : @ " Montpellier " ];
[ maListe addObject : @ " Rennes " ];
[ maListe addObject : @ " Lille " ];
[ maListe addObject : @ " Le Havre " ];
[ maListe addObject : @ " Reims " ];
[ maListe addObject : @ " Le Mans " ];
[ maListe addObject : @ " Dijon " ];
[ maListe addObject : @ " Grenoble " ];
[ maListe addObject : @ " Brest " ];
}

Copier ce code
B
Code web : 156087


Il n'y a rien de bien compliqu dans ces instructions. L'objet maListe est instanci :
1

maListe = [[ NSMutableArray alloc ] init ];

Puis plusieurs valeurs sont mmorises dans le tableau l'aide de la mthode addObject :
1

[ maListe addObject : @ " Paris " ];

Nous allons maintenant mettre en place les mthodes qui vont  alimenter  le contrle
Picker View :
1
2
3
4
5
6
7
8
9

- ( NSInteger ) numberOfComponentsInPickerView :( UIPickerView *)


pickerView {
return 1 ;
}
- ( NSInteger ) pickerView :( UIPickerView *) pickerView
numberOfRowsInComponent :( NSInteger ) component {
return [ maListe count ];
}
- ( NSString *) pickerView :( UIPickerView *) pickerView titleForRow
:( NSInteger ) row forComponent :( NSInteger ) component {
return [ maListe objectAtIndex : row ];
}

Copier ce code
B
Code web : 163348

215

CHAPITRE 12.

LES INFORMATIONS TABULAIRES

La valeur retourne par la mthode numberOfComponentsInPickerView dnit le nombre


de colonnes dans le Picker View. Ici, une seule colonne :
return 1 ;

La valeur retourne par la mthode numberOfRowsInComponent dnit le nombre d'lments achs dans le Picker View. En ce qui nous concerne, ce nombre est gal au
nombre d'lments stocks dans le tableau maListe :
return [ maListe count ];

Enn, la valeur retourne par la mthode titleForRow est aecte l'lment d'index
row. Il sut de l'extraire du tableau maListe via la mthode objectAtIndex :
return [ maListe objectAtIndex : row ];

Pour terminer, nous allons dnir la mthode qui va mettre jour le Label lorsqu'un
lment du Picker View sera slectionn :
-( void ) pickerView :( UIPickerView *) pickerView didSelectRow :(
NSInteger ) row
inComponent :( NSInteger ) component {
status . text = [ maListe objectAtIndex : row ];
}

1
2
3
4

Lorsque l'utilisateur clique sur une entre, le NSInteger row contient l'index de cette
entre. Pour retrouver la valeur correspondante, il sut donc de la lire dans le tableau
maListe ([maListe objectAtIndex:row]). Cette valeur est alors copie dans la composante text du Label (status.text =). En d'autres termes, elle est ache dans le
Label.
Vous pouvez copier le code de l'application en utilisant le code web suivant.


Copier
ce
code
B
Code web : 337610


ViewController.h
1
2
3
4
5
6
7
8
9
10
11

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController <
UIPickerViewDelegate , UIPickerViewDataSource >
{
NSMutableArray * maListe ;
}
@property ( weak , nonatomic ) IBOutlet UIView * pv ;
@property ( weak , nonatomic ) IBOutlet UILabel * status ;
@end

ViewController.m

216

LISTES D'INFORMATIONS SUR UNE OU PLUSIEURS COLONNES

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

# import " ViewController . h "


@implementation ViewController
@synthesize pv ;
@synthesize status ;
- ( void ) didReceiveMemoryWarning
{
[ super didReceiveMemoryWarning ];
// Release any cached data , images , etc that aren 't in use .
}
# pragma mark - View lifecycle
- ( void ) viewDidLoad
{
[ super viewDidLoad ];
maListe = [[ NSMutableArray alloc ] init ];
[ maListe addObject : @ " Paris " ];
[ maListe addObject : @ " Lyon " ];
[ maListe addObject : @ " Marseille " ];
[ maListe addObject : @ " Toulouse " ];
[ maListe addObject : @ " Nantes " ];
[ maListe addObject : @ " Nice " ];
[ maListe addObject : @ " Bordeaux " ];
[ maListe addObject : @ " Montpellier " ];
[ maListe addObject : @ " Rennes " ];
[ maListe addObject : @ " Lille " ];
[ maListe addObject : @ " Le Havre " ];
[ maListe addObject : @ " Reims " ];
[ maListe addObject : @ " Le Mans " ];
[ maListe addObject : @ " Dijon " ];
[ maListe addObject : @ " Grenoble " ];
[ maListe addObject : @ " Brest " ];
}
- ( NSInteger ) numberOfComponentsInPickerView :( UIPickerView *)
pickerView {
return 1 ;
}
- ( NSInteger ) pickerView :( UIPickerView *) pickerView
numberOfRowsInComponent :( NSInteger ) component {
return [ maListe count ];
}
- ( NSString *) pickerView :( UIPickerView *) pickerView titleForRow
:( NSInteger ) row forComponent :( NSInteger ) component {
return [ maListe objectAtIndex : row ];
}

217

CHAPITRE 12.

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
88

LES INFORMATIONS TABULAIRES

-( void ) pickerView :( UIPickerView *) pickerView didSelectRow :(


NSInteger ) row
inComponent :( NSInteger ) component {
status . text = [ maListe objectAtIndex : row ];
}
- ( void ) viewDidUnload
{
[ self setPv : nil ];
[ self setStatus : 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

Slection d'une date dans un contrle spcialis


Le contrle Date Picker est trs proche du contrle Picker View, ceci prs qu'il est
spcialis dans la slection de dates et d'heures. Sa mise en uvre est galement plus
218

SLECTION D'UNE DATE DANS UN CONTRLE SPCIALIS

simple que celle d'un Picker View.


titre d'exemple, nous allons dnir une application qui permettra l'utilisateur de
slectionner une date et une heure dans un contrle Date Picker. Un clic sur le bouton
Slectionner provoquera l'achage de la slection dans un contrle Label, comme
la gure 12.16.

Figure 12.16  Voici quoi ressemblera notre application

Rien de trs original me direz-vous ! Cependant, cette petite application va aborder les
points essentiels concernant le contrle Date Picker. Allez, retroussez vos manches !
Dnissez une nouvelle application base sur le modle Single View Application et
donnez-lui le nom  datePicker . Slectionnez le chier MainStoryboard.storyboard
et ajoutez-y un contrle Date Picker, un contrle Round Rect Button et un contrle
Label en utilisant Interface Builder. Double-cliquez sur le bouton et tapez  Slectionner . Double-cliquez sur le Label et tapez  Choisissez une date  puis appuyez
sur Slectionner. Enn, positionnez ces trois contrles pour obtenir quelque chose
s'approchant de la gure 12.17.
Cliquez sur l'icne Show the Assistant editor dans la barre d'outils de Xcode et
dnissez les outlets et actions suivants :
Contrle

UIDatePicker
UILabel
UIButton

Outlet ou Action Nom

Outlet
Outlet
Action

dp
status
selectionner
219

CHAPITRE 12.

LES INFORMATIONS TABULAIRES

Figure 12.17  Positionnez les contrles comme ceci

220

SLECTION D'UNE DATE DANS UN CONTRLE SPCIALIS

Le chier ViewController.h doit maintenant ressembler ceci :


1
2
3
4
5
6
7
8

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
@property ( weak , nonatomic ) IBOutlet UIDatePicker * dp ;
@property ( weak , nonatomic ) IBOutlet UILabel * status ;
- ( IBAction ) selectionner :( id ) sender ;
@end

Rien de bien mchant l-dedans. Maintenant, vous devez tre habitus dnir des
interfaces avec Interface Builder et rfrencer les contrles dans le code en les contrleglissant-dposant depuis la zone d'dition sur le chier d'en-ttes.
Si vous le souhaitez, vous pouvez ds prsent lancer l'application en cliquant sur Run.
Le contrle Date Picker est oprationnel, mme si aucune instruction n'a encore t
crite dans le chier .m.
Il se peut que le contrle Date Picker ache la date au format amricain.
Pour rgler ce problme, lancez l'application Settings dans le simulateur, cliquez sur Gnral, puis sur International. Rglez Language sur Franais
et Format rgional sur France.

Pour terminer l'application, nous allons donner vie au bouton en crivant quelques
lignes de code. Cliquez sur datePickerViewController.m dans le volet de navigation
et compltez la mthode selectionner comme suit :
1
2
3
4
5
6

- ( IBAction ) selectionner :( id ) sender {


NSLocale * frLocale = [[ NSLocale alloc ]
initWithLocaleIdentifier : @ " fr_FR " ];
NSDate * pickerDate = [ dp date ];
NSString * select = [[ NSString alloc ] initWithFormat : @ " % @ " , [
pickerDate descriptionWithLocale : frLocale ]];
status . text = select ;
}

Examinons ces instructions. Dans un premier temps, l'objet frLocale de type NSLocale
est dni (NSLocale *frLocale = [[[NSLocale alloc] ...) puis initialis avec les
paramtres rgionaux fr_FR (initWithLocaleIdentifier:@"fr_FR") :
1

NSLocale * frLocale = [[ NSLocale alloc ] initWithLocaleIdentifier


: @ " fr_FR " ];

Cet objet sera utilis par la suite pour dnir le format de la date et de l'heure
acher dans le Label. Ici, nous avons utilis le format fr_FR pour que les dates et
heures soient aches  la franaise .
Pour faciliter l'criture, l'objet NSDate pickerDate est dni et initialis avec la date
slectionne par l'utilisateur dans le contrle Date Picker :
1

NSDate * pickerDate = [ dp date ];

221

CHAPITRE 12.

LES INFORMATIONS TABULAIRES

L'instruction suivante dnit l'objet select de classe NSString et l'initialise avec la


date slectionne par l'utilisateur (pickerDate) mise en forme selon les conventions
franaises (descriptionWithLocale:frLocale) :
1

NSString * select = [[ NSString alloc ] initWithFormat : @ " % @ " , [


pickerDate descriptionWithLocale : frLocale ]];

Enn, la date et l'heure mmorises dans l'objet select sont aectes la composante
du Label, et donc, aches dans le Label :

text
1

status . text = select ;

Il faut bien l'avouer, la mise en uvre d'un contrle Date

Picker est vraiment simple !

En rsum
 Les contrles Table View sont utiliss pour acher des listes d'informations sur
une colonne. Pour faciliter l'criture d'une application base sur l'utilisation d'un
Table View et des vues dtailles correspondantes, le plus simple consiste utiliser
le modle Master-Detail Application.
 Pour relier les lments de la vue Master la vue Detail, il sut de crer un Segue
(Push, Modal ou Custom) en contrle-glissant-dposant une cellule de la vue Master
sur la vue Detail dans le canevas.
 Les contrles Table View ont une variante : les Picker View. Outre leur aspect
 roulette 3D , ces contrles peuvent acher des informations sur une ou plusieurs
colonnes, et chaque colonne peut comporter un nombre d'informations dirent.
 Le contrle Date Picker est trs proche du contrle Picker View, ceci prs qu'il
est spcialis dans la slection de dates et d'heures. Sa mise en uvre est galement
plus simple que celle d'un Picker View.

222

Chapitre

13

Les contrles d'action


Dicult :

omme leur nom le laisse supposer, les contrles d'action sont utiliss pour eectuer
des actions lorsque l'utilisateur interagit avec l'cran de son device.
Dans cette section, vous allez apprendre relier un contrle d'action (bouton de commande,
slider, zone de texte modiable, etc.) au code de l'application an de grer un vnement
utilisateur. Si ncessaire, vous pourrez mme crer plusieurs liaisons pour grer plusieurs
types d'actions. La technique est la mme, seul le code excuter change.
C'est (entre autres) en choisissant soigneusement les contrles d'action utiliss qu'une
application sera intuitive, agrable et facile utiliser. Tournez vites les pages et dcouvrez
les contrles d'action utilisables sur un device iOS 5.

223

CHAPITRE 13.

LES CONTRLES D'ACTION

Boutons
Les boutons sont les contrles d'action de base. Leur apparence peut tre personnalise en utilisant Interface Builder ou des instructions Objective-C. Vous pouvez par
exemple choisir la forme, le texte, l'image, la couleur d'arrire-plan et encore beaucoup d'autres caractristiques. Interface Builder donne accs cinq types de boutons
prdnis, comme le montre la gure 13.1.

Figure 13.1  Les cinq boutons prdnis par Interface Builder

Pour transformer un bouton par dfaut (Rounded Rect) en un bouton prdni, il


sut de faire votre choix dans la liste droulante Type, comme indiqu la gure 13.2.

Figure 13.2  Vous pouvez faire votre choix dans la liste droulante Type
Pour ceux qui ne sauraient pas encore comment accder aux proprits :
cliquez sur l'icne Hide or show the Utilities dans la barre d'outils, puis
sur l'icne Show the Attributes inspector dans le volet des utilitaires.

Il est galement possible d'ajouter une image un bouton Rounded Rect : insrez une
image de petite taille dans les ressources de l'application et slectionnez-la dans la
224

BOUTONS

proprit Image du bouton. Si ncessaire, compltez cette image avec un texte, comme
la gure 13.3.

Figure 13.3  Il est possible d'ajouter une image en plus du texte un bouton
Si les boutons prdnis ne vous conviennent pas, il est possible de dnir vos
propres boutons  la main . Achez le volet des attributs puis choisissez
Custom dans la proprit Type du bouton. Vous pouvez alors choisir l'image,
le texte et ses caractristiques ainsi que l'arrire-plan du bouton.

Enn, il est galement possible de crer un bouton en utilisant du code Objective-C :


1
2
3

UIButton * monBouton = [ UIButton buttonWithType :


UIButtonTypeInfoDark ];
[ monBouton setCenter : CGPointMake ( 100 . 0f , 100 . 0f ) ];
[ self . view addSubview : monBouton ];

La premire instruction dnit l'objet monBouton, le rattache la classe UIButton et


dnit son type UIButtonTypeInfoDark. La deuxime instruction dnit les coordonnes du centre du bouton. Le premier nombre correspond l'abscisse et le deuxime
l'ordonne, par rapport au coin suprieur gauche de l'cran. Enn, la troisime instruction ajoute le bouton la vue courante.
Si le bouton est de type Rounded Rect, vous pouvez galement dnir sa taille et le
texte qui y est ach :
1

UIButton * monBouton = [ UIButton buttonWithType :


UIButtonTypeRoundedRect ];

225

CHAPITRE 13.

2
3
4

LES CONTRLES D'ACTION

[ monBouton setFrame : CGRectMake ( 100 . 0f , 100 . 0f , 100 . 0f , 20 . 0f ) ];


[ monBouton setTitle : @ " Mon bouton " forState :
UIControlStateNormal ];
[ self . view addSubview : monBouton ];

La premire instruction dnit l'objet monBouton, le rattache la classe UIButton


et dnit son type UIButtonTypeInfoDark. La deuxime instruction dnit la position (les deux premiers paramtres) et les dimensions (les deux derniers paramtres)
du bouton. La troisime instruction dnit le texte ach dans le bouton. Enn, la
quatrime instruction ajoute le bouton la vue courante.
Les boutons relvent de la classe UIButton. L'vnement dclencheur par dfaut est
Touch Up Inside ; en d'autres termes, lorsqu'un doigt est enlev du bouton. Si ncessaire, il est possible d'utiliser plusieurs autres dclencheurs. Par exemple Touch Down
(lorsqu'un doigt est pos sur le bouton), Value Changed (modication du texte du
bouton) ou encore Touch Drag Inside (appui sur le bouton et dplacement du doigt).
J'ai dni une action et une mthode vnementielle pour mon bouton, mais
lorsque j'appuie dessus, rien ne se passe. Est-ce que j'aurais rat quelque
chose ?

Il y a de grandes chances pour que vous n'ayez pas reli le bouton et le code. Contrleglissez-dposez le bouton de la zone d'dition sur le chier d'en-ttes, juste au-dessus
du @end. Au relchement du bouton gauche de la souris, slectionnez Action dans la
liste Connection, donnez un nom l'action et cliquez sur Connect.
Segmented Control

Les contrles Segmented Control sont comparables des onglets. Ils sont utiliss pour
acher ou cacher certains lments en fonction de l'onglet (ou plutt du  segment 
dans le jargon Xcode) slectionn. Ils sont attachs la classe UISegmentedControl.
Supposons par exemple que vous ayez attach plusieurs images votre projet. En
utilisant un Segmented Control, vous pouvez acher une image pour chaque onglet.
Nous allons mettre cela en pratique.
Dnissez une nouvelle application base sur le modle Single View Application
et donnez-lui le nom  onglets . En utilisant Interface Builder, ajoutez au chier
MainStoryboard.storyboard un contrle Segmented Control, un contrle Image View
et un contrle Label. Positionnez et redimensionnez ces contrles pour obtenir quelque
chose comme la gure 13.4.

226

SEGMENTED CONTROL

Figure 13.4  Les contrles doivent tre placs de la sorte

Contrle-glissez-dposez les contrles de la zone d'dition sur le code du chier d'enttes ViewController.h et dnissez les connexions suivantes :
Contrle

Segmented Control
Segmented Control
Image View
Label

Type de liaison Nom

Outlet
Action
Outlet
Outlet

onglets
ongletChange
image
sousTitre

Le chier ViewController.h doit maintenant contenir les instructions suivantes :


1
2
3
4
5
6
7
8
9

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
@property ( weak , nonatomic ) IBOutlet UISegmentedControl *
onglets ;
- ( IBAction ) ongletChange :( id ) sender ;
@property ( weak , nonatomic ) IBOutlet UIImageView * image ;
@property ( weak , nonatomic ) IBOutlet UILabel * sousTitre ;
@end

Cette premire tape eectue, vous allez ajouter un onglet au Segmented Control et
rednir le nom des trois onglets. Commencez par slectionner le Segmented Control
227

CHAPITRE 13.

LES CONTRLES D'ACTION

dans le canevas, cliquez sur l'icne Show the Attributes inspector dans la partie
suprieure duvolet des utilitaires. Inscrivez  3  dans la proprit Segments et appuyez
sur la touche Entre de votre clavier. Le contrle comporte maintenant trois onglets.
Double-cliquez successivement sur chaque onglet dans la zone d'dition et renommezles  Premier ,  Deuxime  et  Troisime . Si les onglets se recouvrent l'un l'autre,
redimensionnez le Segmented Control pour arranger les choses. L'interface doit maintenant ressembler la gure 13.5.

Figure 13.5  L'interface de l'application

Dnissez un dossier  Resources  et ajoutez trois images de 320 x 480 pixels dans ce
dossier. Si cette manipulation vous chappe, reportez-vous la section  Acher une
image  du chapitre 10 (page 159). la gure 13.6 se trouvent les trois images que j'ai
utilises. Elles proviennent de la bibliothque de cliparts de Microsoft Oce.

Figure 13.6  Les trois images utilises dans l'exemple

228

SEGMENTED CONTROL

Tlcharger les images


B
Code web : 760903


Il est temps d'crire quelques lignes de code. Aucune image n'ayant t aecte au
contrle Image View, ni aucun texte au contrle Label, nous allons le faire via la
mthode viewDidLoad.
Cliquez sur ViewController.m dans le volet de navigation et modiez la mthode
viewDidLoad comme suit :
1
2
3
4
5
6
7

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
UIImage * imageCourante = [ UIImage imageNamed : @ " cheval . jpg " ];
[ image setImage : imageCourante ];
sousTitre . text = @ " Un cheval et sa cavali re " ;
}

La ligne 4 dnit l'objet UIImage imageCourante (UIImage *imageCourante) et lui


aecte l'image  cheval.jpg  qui se trouve dans les ressources de l'application (=
[UIImage imageNamed: @"cheval.jpg"]) :
1

UIImage * imageCourante = [ UIImage imageNamed : @ " cheval . jpg " ];

La ligne 5 aecte l'objet imageCourante au contrle imageView


son achage :
1

image,

et provoque

[ image setImage : imageCourante ];

Enn, la ligne 6 ache un texte dans le Label :


1

sousTitre . text = @ " Un cheval et sa cavali re " ;

Pour terminer l'application, il ne reste plus qu' ragir aux changements d'onglets en
achant les images et le texte correspondants. Dplacez-vous dans la partie infrieure
du code et compltez la mthode ongletChange comme suit :
1
2
3
4
5
6
7
8
9
10
11
12
13
14

- ( IBAction ) ongletChange :( id ) sender {


if ( onglets . selectedSegmentIndex == 0 )
{
UIImage * imageCourante = [ UIImage imageNamed : @ " cheval . jpg "
];
[ image setImage : imageCourante ];
sousTitre . text = @ " Un cheval et sa cavali re " ;
}
if ( onglets . selectedSegmentIndex == 1 )
{
UIImage * imageCourante = [ UIImage imageNamed : @ " chien . jpg "
];
[ image setImage : imageCourante ];
sousTitre . text = @ " Un chien ";
}
if ( onglets . selectedSegmentIndex == 2 )

229

CHAPITRE 13.

15
16
17
18
19
20

LES CONTRLES D'ACTION

UIImage * imageCourante = [ UIImage imageNamed : @ " chat . jpg " ];


[ image setImage : imageCourante ];
sousTitre . text = @ " Un chat ";

Cette mthode est appele chaque fois que l'utilisateur change d'onglet. Pour savoir quel onglet a t slectionn, il sut de lire la valeur stocke dans la proprit
selectedSegmentIndex du contrle Segmented Index (ici onglets). Cette proprit
vaut 0 lorsque le premier onglet a t slectionn, 1 lorsque le deuxime onglet a t
slectionn, 2 lorsque le troisime onglet a t slectionn, et ainsi de suite. Comme
vous pouvez le remarquer, la mthode ongletChange est compose de trois blocs d'instructions peu prs similaires. Vous pouvez excuter le projet.
la gure 13.7 se trouve le rsultat que j'ai obtenu.

Figure 13.7  Le rsultat obtenu

Zones de texte
Les contrles Text Field sont des zones de texte monolignes librement ditables par
l'utilisateur. Lorsque l'utilisateur clique dans une zone de texte, le clavier intgr s'afche dans la partie infrieure de l'cran, comme la gure 13.8.
230

ZONES DE TEXTE

Figure 13.8  Un clavier apparat dans la zone infrieure de l'cran

Lorsque l'utilisateur a termin la saisie, il appuie sur la touche Return du clavier


intgr. Ce dernier doit alors disparatre. Pour cela, plusieurs actions sont ncessaires.
Dans le chier .h

Supposons que votre application soit base sur le modle Single View Application,
qu'elle ait pour nom tf (comme Text Field) et que son canevas contienne un contrle
Text Field. Vous allez ajouter la dclaration qui apparat ligne 5 dans le chier
ViewController.h :
1
2
3
4
5
6
7

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
- ( IBAction ) saisieReturn :( id ) sender ;
@end

Dans le chier .m

Dnissez le code relatif la mthode saisieReturn dans le chier ViewController.m :


1
2
3
4

- ( IBAction ) saisieReturn :( id ) sender


{
[ sender resignFirstResponder ];
}

Le message [sender resignFirstResponder]; indique son destinataire qu'il n'est


plus le premier rpondant. Si cette mthode est relie l'vnement Did End on Exit
de la zone de texte, le clavier disparatra, puisque la zone de texte n'aura plus le focus.
Dans la prochaine tape, nous allons donc relier l'vnement Did End on Exit et la
mthode saisieReturn.
231

CHAPITRE 13.

LES CONTRLES D'ACTION

Dans Interface Builder

Comme la gure 13.9 :


 cliquez sur MainStoryboard.storyboard dans le volet de navigation (1) ;
 cliquez sur la zone de texte dans la vue (2) ;
 achez le volet des utilitaires en cliquant sur Hide or Show the Utilities (3) ;
 achez les connexions en cliquant sur Show the Connections Inspector (4) ;
 reprez le bouton radio droite de Did End On Exit, pointez-le, maintenez le bouton
gauche de la souris enfonc et dplacez la souris sur l'icne View Controller (5) ;
 au relchement du bouton gauche de la souris, slectionnez saisieReturn dans le
menu (6).

Figure 13.9  Il faut relier l'vnement Did

End on Exit et la mthode saisieReturn

Pour rcuprer le contenu d'une zone de texte, il sut d'utiliser sa proprit text. Nous
allons illustrer cette proprit en dnissant une mini-application compose d'une zone
de texte et d'un label, comme la gure 13.10.
Pour obtenir ce rsultat, commencez par dnir une application base sur le modle
Single View Application, ajoutez un contrle Text Field et un contrle Label au
canevas.
232

ZONES DE TEXTE

Figure 13.10  Voici quoi doit ressembler notre application

L'application n'a pas encore l'apparence souhaite. Vous devez modier deux paramtres dans l'inspecteur des attributs :
 cliquez sur le contrle Text Field et crivez  --- Entrez du texte ici ---  dans le
paramtre Placeholder ;
 cliquez sur le contrle Label et tapez  Aucun texte n'a t entr  dans le paramtre
Text.
Pour les tourdis, je rappelle que l'inspecteur des attributs est ach en cliquant
respectivement sur l'icne Hide or show the Utilities et Show the Attributes
inspector. Il sut alors de modier l'attribut souhait .
Vous allez maintenant relier ces deux contrles au code de l'application :
 Cliquez sur l'icne Show the Assistant editor dans la barre d'outils de Xcode.
 Contrle-glissez-dposez le contrle Text Field du canevas dans le code source du
chier ViewController.h et crez l'outlet saisie.
 Contrle-glissez-dposez le contrle Label du canevas dans le code source du chier
ViewController.h et crez l'outlet status.
Aprs ces manipulations, le chier ViewController.h devrait contenir les instructions
suivantes :
1
2
3

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController

233

CHAPITRE 13.

4
5
6
7
8
9

LES CONTRLES D'ACTION

- ( IBAction ) saisieReturn :( id ) sender ;


@property ( weak , nonatomic ) IBOutlet UITextField * saisie ;
@property ( weak , nonatomic ) IBOutlet UILabel * status ;
@end

Nous allons supposer que l'eacement du clavier a t mis en place lorsque l'utilisateur
appuie sur la touche Return, comme indiqu prcdemment. Une ligne supplmentaire
dans la mthode saisieReturn va sure pour acher le contenu de la zone de texte
dans le Label (ici la ligne 3) :
1
2
3
4
5

- ( IBAction ) saisieReturn :( id ) sender


{
status . text = [ NSString stringWithFormat : @ " % @ % @ " , @ " Vous
avez tap : " , saisie . text ];
[ sender resignFirstResponder ];
}

La proprit text du contrle Label (status.text) est initialise avec l'objet NSString
retourn par le message qui suit le signe  = . Cet objet est constitu par la concatnation (c'est--dire l'ajout) de deux textes (stringWithFormat: @"%@%@") : la chane
 Vous avez tap  (@"Vous avez tap : ") et le contenu du contrle Text Field
(saisie.text).

Curseurs
Les contrles Slider (gure 13.11) sont des curseurs horizontaux dont la position est
ajustable par l'utilisateur. Vous les utiliserez pour faciliter la slection de valeurs dans
des plages.

Figure 13.11  Un contrle Slider

Ces contrles relvent de la classe UISlider. Il est possible de les personnaliser dans
Interface Builder en dnissant :
 une image pour reprsenter la valeur minimale et une autre pour reprsenter la valeur
maximale ;
 les valeurs minimales et maximales ;
 la valeur par dfaut au lancement de l'application.
La position du curseur est accessible tout moment dans la proprit value.
Pour illustrer le fonctionnement de ce contrle, nous allons crer une mini-application
qui ache dans un Label la position d'un Slider, et ce chaque modication du
curseur par l'utilisateur.
234

INTERRUPTEURS

Dnissez un nouveau projet en utilisant le modle Single View Application et


donnez-lui le nom  slider . Ajoutez un Slider et un Label au canevas. Reliez le
Label au chier .h ; pour cela, eectuez un contrle-glisser-dposer du Label dans le
chier .h et donnez le nom status l'outlet ainsi cr.
Reliez le Slider au chier .h. Pour cela, eectuez un contrle-glisser-dposer du Slider
dans le chier .h. Au relchement du bouton gauche de la souris, slectionnez Action
dans la liste Connection, choisissez Value Changed dans la liste Event et tapez  sl 
dans la zone de texte Name.
Le chier .h doit maintenant ressembler ceci :
1
2
3
4
5
6
7

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
@property ( weak , nonatomic ) IBOutlet UILabel * status ;
- ( IBAction ) sl :( id ) sender ;
@end

Pour complter ces dnitions, vous devez dnir quelques lignes de code dans la mthode sl qui, rappelons-le, ragit l'vnement Value Changed du Slider :
1
2
3
4
5

- ( IBAction ) sl :( id ) sender {
UISlider * slider = ( UISlider *) sender ;
status . text = [ NSString stringWithFormat : @ " % 1 . 2f " , slider .
value ];
}

La ligne 2 dnit l'objet slider de type UISlider et le relie au Slider qui est l'origine
de l'vnement. La ligne 3 convertit la proprit value du Slider (slider.value)
en un objet NSString (NSString stringWithFormat:@"%1.2f", ...). L'objet ainsi
obtenu est plac dans la proprit text du Label status (status.text = ...), ce
qui provoque l'achage de la valeur du curseur dans le label.

Interrupteurs
Vous utiliserez un contrle Switch chaque fois qu'il est ncessaire de mettre en place
un interrupteur marche/arrt, comme celui utilis dans les rglages du device pour le
mode avion (gure 13.12).
Le contrle Switch relve de la classe UISwitch. La proprit boolenne on permet
de connatre son tat et la mthode setOn de le modier. Voici la syntaxe de cette
mthode :
1

- ( void ) setOn :( BOOL ) on animated :( BOOL ) animated

Donnez la valeur :
235

CHAPITRE 13.

LES CONTRLES D'ACTION

Figure 13.12  Un contrle Switch pour le mode avion

ou NO au paramtre on selon que vous vouliez mettre l'interrupteur sur ON ou


sur OFF.
 YES ou NO au paramtre animated selon que vous vouliez changer l'tat de l'interrupteur ; c'est--dire avec ou sans animation.
Pour illustrer l'utilisation de ce contrle, nous allons dnir une mini-application qui
ache l'tat d'un interrupteur marche/arrt chaque fois que celui-ci change.
Dnissez un nouveau projet en utilisant le modle Single View Application et
donnez-lui le nom  switch . Ajoutez un Switch et un Label au canevas.
Reliez le Label au chier .h en eectuant un contrle-glisser-dposer du Label dans
le chier .h et donnez le nom  status  l'outlet ainsi cr.
Reliez le Switch au chier .h en eectuant un contrle-glisser-dposer du Switch dans
le chier .h. Au relchement du bouton gauche de la souris, slectionnez Action dans
la liste Connection, choisissez Value Changed dans la liste Event et tapez  sw  dans
la zone de texte Name.
Le chier .h doit maintenant ressembler ceci :
1
2
3
4
5
6
7

YES

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
@property ( weak , nonatomic ) IBOutlet UILabel * status ;
- ( IBAction ) sw :( id ) sender ;
@end

Pour complter ces dnitions, vous devez dnir quelques lignes de code dans la mthode sw qui, rappelons-le, ragit l'vnement Value Changed du Switch. Cliquez
sur ViewController.m dans le volet de navigation puis modiez la mthode sw comme
suit :
1
2
3
4
5
6
7

- ( IBAction ) sw :( id ) sender {
UISwitch * uis = ( UISwitch *) sender ;
if ( uis . on == TRUE )
status . text = @ " Le switch est sur ON " ;
else
status . text = @ " Le switch est sur OFF " ;
}

La deuxime ligne dnit l'objet uis de classe UISwitch et le relie au switch qui est
236

CONTRLES DE PAGE

l'origine de l'vnement. La ligne suivante teste la valeur de la proprit on du switch.


Si cette proprit vaut TRUE, cela signie que l'interrupteur vient d'tre initialis ON.
Le texte  Le switch est sur ON  est alors ach dans le label :
1

status . text = @ " Le switch est sur ON " ;

Dans le cas contraire, cela signie que l'interrupteur vient d'tre initialis OFF. Le
texte  Le switch est sur OFF  est alors ach dans le label :
1
2

else
status . text = @ " Le switch est sur OFF " ;

Contrles de page
Les contrles Page Control sont utiliss dans une vue qui comporte plusieurs pages.
Ils permettent l'utilisateur :
1. de savoir o se situe la page courante dans l'ensemble des pages ;
2. de se dplacer dans l'ensemble des pages.
Ces contrles relvent de la classe UIPageControl. Pour vous montrer comment les
utiliser, nous allons dvelopper une application dans laquelle un contrle Scroll View
contient des zones colores mises bout bout. Comme vous pouvez le voir sur l'image
13.13, le Scroll View est bien plus large que l'cran de l'iPhone : il comporte cinq
zones colores de la mme taille que l'cran.

Figure 13.13  Le contrle Scroll

View contient des zones colores mises bout bout

Dnissez une nouvelle application base sur le modle Single View Application et
donnez-lui le nom  page . En utilisant Interface Builder, ajoutez un contrle Scroll
View au chier MainStoryboard.storyboard, et redimensionnez-le pour qu'il occupe
la quasi-totalit de l'cran.
237

CHAPITRE 13.

LES CONTRLES D'ACTION

Contrle-glissez-dposez le contrle Scroll View de la zone d'dition dans le code du


chier d'en-ttes ViewController.m et dnissez l'outlet sv. Le chier d'en-ttes doit
maintenant ressembler ceci :
1
2
3
4
5
6

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
@property ( weak , nonatomic ) IBOutlet UIScrollView * sv ;
@end

Nous allons maintenant dnir les rectangles colors qui seront achs dans le contrle
Scroll View.
Pour qu'un rectangle reprsente une page dans le Scroll View, il sut de lui donner la mme taille que le Scroll View. Pour cela, nous allons utiliser la mthode
viewDidLoad. Cliquez sur ViewController.m dans le volet de navigation et compltez
la mthode viewDidLoad comme ceci :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
NSArray * couleurs = [ NSArray arrayWithObjects :[ UIColor
redColor ] , [ UIColor greenColor ] , [ UIColor blueColor ] , [
UIColor cyanColor ] , [ UIColor yellowColor ] , nil ];
for ( int i = 0 ; i < couleurs . count ; i ++)
{
// D finition d 'un rectangle
CGRect rectangle ;
rectangle . origin . x = sv . frame . size . width * i ;
rectangle . origin . y = 0 ;
rectangle . size = sv . frame . size ; // Le rectangle a la m me
dimension que le UIScrollView

// Ajout de la vue correspondante


UIView * subview = [[ UIView alloc ] initWithFrame : rectangle ];
subview . backgroundColor = [ couleurs objectAtIndex : i ];
[ sv addSubview : subview ];

sv . contentSize = CGSizeMake ( sv . frame . size . width * couleurs .


count , sv . frame . size . height ) ;

Copier ce code
B
Code web : 898165


La ligne 4 dnit un objet NSArray nomm couleurs (NSArray *couleurs) et l'initialise avec cinq couleurs prdnies.
Le bloc d'instructions suivant (lignes 5 17) dnit les cinq rectangles et les transforme
en vues du contrle Scroll View. Pour bien faire les choses, la boucle for utilise
238

CONTRLES DE PAGE

le nombre de couleurs dnies dans le tableau couleurs (couleurs.count) comme


borne suprieure. Ainsi, si vous voulez dnir plus ou moins de couleurs, l'application
fonctionnera tout aussi bien :
1
2
3
4

for ( int i = 0 ; i < couleurs . count ; i ++)


{
...
}

Les rectangles sont des objets CGRect. La premire instruction de la boucle (ligne 8)
commence par dnir un objet rectangle de type CGRect :
1

CGRect rectangle ;

Les trois instructions suivantes dnissent l'origine et la taille du rectangle :


1
2
3

rectangle . origin . x = sv . frame . size . width * i ;


rectangle . origin . y = 0 ;
rectangle . size = sv . frame . size ;

Remarquez la faon dont est dnie l'abscisse (rectangle.origin.x) du rectangle :


1

rectangle . origin . x = sv . frame . size . width * i ;

La proprit frame.size.width de l'objet UIScrollView sv donne la largeur de ce


contrle. En la multipliant par l'index de la boucle, qui vaut conscutivement 0, 1, 2,
3 puis 4, on obtient les valeurs suivantes :
Index

0
1
2
3
4

rectangle.origin.x

0
Largeur de sv
2 largeurs de sv
3 largeurs de sv
4 largeurs de sv

Les cinq rectangles colors seront donc placs cte cte horizontalement.
Les instructions suivantes (lignes 14 16) dnissent les direntes vues qui composent l'objet Scroll View. Pour cela, un objet subview de classe UIView est dni (UIView *subview) et initialis avec le rectangle cr quelques lignes plus haut
(initWithFrame:rectangle) :
1

UIView * subview = [[ UIView alloc ] initWithFrame : rectangle ];

La couleur de cet objet est alors initialise avec la couleur dnie dans l'lment d'index
i du tableau :
1

subview . backgroundColor = [ couleurs objectAtIndex : i ];

La sous-vue est enn dnie en utilisant l'objet subview :


1

[ sv addSubview : subview ];

239

CHAPITRE 13.

LES CONTRLES D'ACTION

Vous pouvez lancer l'application et constater (oh merveille !) qu'il est possible de scroller
horizontalement dans le Scroll View. Vous allez maintenant ajouter un contrle Page
Control au chier ViewController.xib. Par dfaut, le nombre de pages accessibles via
un Page Control est gal trois. Dans notre cas, nous devons scroller travers cinq
pages. Il faut donc modier le nombre de pages par dfaut. Cliquez sur le Page Control
dans la zone d'dition, achez le volet des attributs (si ncessaire en cliquant sur Hide
or show the Utilities puis sur Show the Attributes inspector) et modiez la
valeur de l'attribut Pages, comme indiqu la gure 13.14.

Figure 13.14  Il faut modier le nombre de pages accessibles par dfaut

Dnissez un outlet et une action pour le contrle Page Control et nommez-les (respectivement)  laPage  et  changePage . Le chier d'en-ttes doit maintenant ressembler
ceci :
1
2
3
4
5
6
7
8

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
@property ( weak , nonatomic ) IBOutlet UIScrollView * sv ;
@property ( weak , nonatomic ) IBOutlet UIPageControl * laPage ;
- ( IBAction ) changePage :( id ) sender ;
@end

Pour que le Page Control puisse tre mis jour lorsque l'utilisateur change de page
en utilisant une gestuelle de glisser, il est ncessaire d'tre inform de cette gestuelle.
Pour cela, nous dlguerons cette tche au Scroll View. Il est donc ncessaire :
1. d'ajouter le protocole UIScrollViewDelegate dans le contrleur de vue, c'est-240

CONTRLES DE PAGE

dire dans le chier ViewController.h ;


2. de connecter le delegate du Scroll View au contrleur de vue.
quoi vont servir ces deux tapes au juste ? Je ne suis pas sr de bien
comprendre.

Elles vont permettre d'crire dans le code du contrleur de vue (ViewController.m)


les mthodes vnementielles en rapport avec le contrle Scroll View. En eet, en
ajoutant le delegate UIScrollViewDelegate au contrleur de vue et en le reliant au
contrleur de vue, ce dernier sera capable de traiter les vnements du contrle Scroll
View.
La premire tape se fait en spciant le protocole dans la dclaration de l'interface :
1
2
3
4

@interface ViewController : UIViewController <


UIScrollViewDelegate >
{
...
}

La deuxime tape se fait en cliquant sur le contrle Scroll View dans le canevas (1),
puis en glissant-dposant le cercle droite de delegate sur l'icne View Controller
(2), comme la gure 13.15.

Figure 13.15  Un contrle-glisser-dposer sur l'icne View

Controller

Retournons au code. Cliquez sur ViewController.m dans le volet de navigation.


241

CHAPITRE 13.

LES CONTRLES D'ACTION

Le contrleur de vue tant le dlgu du Scroll View, nous allons utiliser une mthode
de ce dernier pour mettre jour le Page Control. Insrez la mthode suivante un
endroit quelconque dans le code. Par exemple juste avant la mthode viewDidLoad :
1
2
3
4
5

- ( void ) scrollViewDidScroll :( UIScrollView *) sender {


CGFloat largeurPage = sv . frame . size . width ;
int page = floor (( sv . contentOffset . x - largeurPage / 2 ) /
largeurPage ) + 1 ;
laPage . currentPage = page ;
}

Cette mthode est excute lorsque l'utilisateur dplace horizontalement le Scroll


View. La ligne 2 stocke la largeur d'une page (c'est--dire celle du Scroll View) dans
la variable CGFloat largeurPage :
1

CGFloat largeurPage = sv . frame . size . width ;

La ligne 3 calcule le numro de la page ache dans le Scroll View. Ce numro change
lorsque la vue est dcale de plus de la moiti de l'cran (gure 13.16).

Figure 13.16  Le numro de page change lorsque la vue est dcale de plus de la

moiti de l'cran

Le calcul parat complexe, mais il n'en est rien. La proprit sv.ContentOffset.x


reprsente le dcalage de l'lment ach dans le Scroll View. Si on lui soustrait la
moiti de la largeur de la page, et qu'on divise le rsultat par la largeur de la page, on
obtient :
 0 lors du scroll de la page 1 la page 2
 1 lors du scroll de la page 2 la page 3
 etc.
242

CONTRLES DE PAGE

En ajoutant 1 cette valeur, on obtient exactement ce qui est recherch, savoir le


numro de la page vers laquelle l'utilisateur se dplace.
Toujours dans le ou ? Passons une application numrique. Nous allons supposer que
le device utilis est un iPhone 3G. Bien sr, ce raisonnement fonctionne sur tous les
autres devices, mais il fallait bien en choisir un pour passer l'application numrique.
La rsolution d'un iPhone 3G est de 320 x 480 pixels. Supposons que l'utilisateur soit
en train d'eectuer une gestuelle pour passer du premier cran au deuxime (comme
sur la gure prcdente). Examinons les valeurs des dirents lments contenus dans la
formule floor((sv.contentOffset.x - largeurPage / 2) / largeurPage) + 1.
L'lment

sv.contentOset.x
sv.contentOset.x - largeurPage / 2
(sv.contentOset.x - largeurPage / 2) / largeurPage
oor((sv.contentOset.x - largeurPage / 2) / largeurPage)
oor((sv.contentOset.x - largeurPage / 2) / largeurPage) + 1

va passer de . . . . . .

0 320
-160 160
-0.5 0.5
-1 jusqu'au milieu de
l'cran, 0 aprs
0 jusqu'au milieu de
l'cran, 1 aprs

Libre vous de dcomposer les calculs pour le passage du deuxime au troisime cran,
du troisime au quatrime et du quatrime au cinquime. Vous verrez, cela fonctionne.
Si vous vous demandez comment j'ai pu trouver cette formule, eh bien, je me suis
demand quel rsultat je voulais obtenir et aprs deux ou trois essais infructueux, je
suis arriv dnir la bonne formule. Cette approche fonctionne bien pour toutes sortes
de formules, qu'elles soient plus simples ou plus complexes. . .
Retournons au code de l'application. Pour mettre jour en consquence le Page
Control, il sut d'aecter la valeur que l'on vient de calculer sa proprit currentPage :
1

laPage . currentPage = page ;

Pour terminer, nous allons complter la mthode action changePage pour ragir aux
actions de l'utilisateur sur le Page Control. En eet, pour le moment, ce contrle est
juste utilis pour acher la page active, mais pas pour changer de page. Rassurez-vous :
le code sera bien plus simple que le prcdent.
Localisez la mthode changePage et compltez-la comme suit :
1
2
3
4
5
6
7

- ( IBAction ) changePage :( id ) sender {


CGRect frame ;
frame . origin . x = sv . frame . size . width * laPage . currentPage ;
frame . origin . y = 0 ;
frame . size = sv . frame . size ;
[ sv scrollRectToVisible : frame animated : YES ];
}

La ligne 2 dnit la variable frame de type CGRect. Le code se poursuit en dnissant


l'abscisse et l'ordonne de l'achage. Si vous n'avez qu'une vague ide de ce que reprsentent ces termes mathmatiques, la gure 13.17 va vous rappeler de vieux souvenirs.
243

CHAPITRE 13.

LES CONTRLES D'ACTION

Figure 13.17  Abscisse et ordonne

La ligne 3 dnit le dcalage en abscisse (frame.origin.x) de l'achage :


frame . origin . x = sv . frame . size . width * laPage . currentPage ;

Ce dcalage est calcul en multipliant le numro de la page courante par la largeur


d'une page.
L'ordonne de l'achage est toujours gale zro :
frame . origin . y = 0 ;

Et la proprit size du rectangle est mise jour avec les composantes x et y qui
viennent d'tre calcules :
frame . size = sv . frame . size ;

Il ne reste plus qu' mettre jour l'achage dans le Scroll View en dnissant
le rectangle visible (scrollRectToVisible:frame) et en demandant une animation
(animated:YES) :
1

[ sv scrollRectToVisible : frame animated : YES ];

Vous pouvez (enn) excuter l'application et proter du rsultat !

En rsum
 Les boutons sont les contrles d'action de base. Leur apparence peut tre personnalise en utilisant Interface Builder ou des instructions Objective-C. Vous pouvez
244

CONTRLES DE PAGE







par exemple choisir la forme, le texte, l'image, la couleur d'arrire-plan et encore


beaucoup d'autres caractristiques.
Les contrles Segmented Control sont comparables des onglets. Ils sont utiliss pour acher ou cacher certains lments en fonction de l'onglet (ou plutt
du  segment  dans le jargon Xcode) slectionn. Ils sont attachs la classe
UISegmentedControl.
Les contrles Text Field sont des zones de texte monolignes librement ditables
par l'utilisateur. Lorsque l'utilisateur clique dans un Text Field, le clavier intgr
s'ache dans la partie infrieure de l'cran.
Les contrles Slider sont des curseurs horizontaux dont la position est ajustable par
l'utilisateur. Vous les utiliserez pour faciliter la slection de valeurs dans des plages.
Vous utiliserez un contrle Switch chaque fois qu'il est ncessaire de mettre en place
un interrupteur marche/arrt, comme celui utilis dans les rglages du device pour
le mode avion.
Les contrles Page Control sont utiliss dans une vue qui comporte plusieurs pages.
Ils permettent l'utilisateur de savoir o se situe la page courante dans l'ensemble
des pages et de se dplacer dans l'ensemble des pages.

245

CHAPITRE 13.

246

LES CONTRLES D'ACTION

Chapitre

14

Barres et tabulations
Dicult :

e chapitre s'intresse aux contrles et aux modles de conception utiliss pour grer
les direntes vues d'une application. Au l des pages, vous apprendrez dnir des
tabulations, mettre en place une barre de navigation, une barre d'outils et une
barre de recherche, mais aussi grer deux vues simultanment sur un iPad, comme dans
l'application de messagerie Mail, fournie en standard avec les iPad 1 et 2.
la n du chapitre, vous aurez une plus grande matrise du storyboard (l'outil de conception
des vues de Xcode). Vous verrez quel point il peut simplier (voire mme automatiser
dans certains cas) la dnition des vues et de leurs interconnexions.
Cette version de Xcode marque clairement le dbut d'une nouvelle re dans la conception
des applications. prsent, le programmeur passe un peu plus de temps peauner son
interface et un peu moins de temps aligner du code. Et de nombreux blocs de code sont
gnrs automatiquement. Qui s'en plaindrait ?

247

CHAPITRE 14.

BARRES ET TABULATIONS

Applications multivues
Les contrles Tab Bar permettent de crer facilement des applications multivues. L'utilisateur passe d'une vue l'autre en cliquant sur les icnes du contrle Tab Bar, comme
le montre la gure 14.1.

Figure 14.1  Les contrles Tab

permettent de changer de vue simplement


Les contrles Tab Bar sont rattachs la classe UITabBar. Nous allons voir comment
les mettre en place en dveloppant une petite application contenant trois vues.
Commencez par dnir une application base sur le modle Tabbed Application et
donnez-lui le nom  tabBar . Cliquez sur MainStoryboard.storyboard dans le volet
de navigation. La gure 14.2 montre comment se prsente le canevas.
Comme vous pouvez le voir :
 un contrleur Tab Bar et deux contrleurs de vues ont automatiquement t insrs
dans le canevas ;
 des liaisons entre le contrleur Tab Bar et les contrleurs de vues ont t mises en
place ;
 un contrle Tab Bar a t insr dans la partie infrieure de la vue principale (Tab
Bar Controller) ;
 les deux vues secondaires contiennent plusieurs contrles.
L'application est dj oprationnelle (gure 14.3). Juste pour vous faire plaisir, cliquez
sur Run et amusez-vous avec les direntes vues qui ont automatiquement t mises en
place lors de la cration de l'application.
248

Bar

APPLICATIONS MULTIVUES

Figure 14.2  Voici comment se prsente le canevas

Figure 14.3  L'application est oprationnelle, il est possible de changer de vue

249

CHAPITRE 14.

BARRES ET TABULATIONS

Cette application comporte deux vues. Pour vous amuser, je vous propose d'insrer une
troisime vue et de la relier au Tab Bar Controller, comme indiqu la gure 14.4.
 Glissez-dposez un View
Controller de la bibliothque d'objets sur le canevas (1).

 Maintenez la touche Ctrl enfonce, cliquez sur le Tab Bar Controller, maintenez
le bouton gauche de la souris enfonc et dirigez son pointeur sur la nouvelle vue (2).
 Relchez la touche Ctrl et le bouton de la souris et slectionnez Relationship viewControllers dans le menu (3).

Figure 14.4  Insrez une troisime vue et reliez-la au Tab

Bar Controller

a y est : vous venez d'insrer une troisime vue dans le projet et de la relier au Tab
Bar Controller. Je sens que vous avez du mal me croire. Allez, cliquez sur Run et
admirez le rsultat (gure 14.5).
Vous allez maintenant modier les icnes des trois vues. Pour cela, vous aurez besoin
d'icnes de 32 x 32 pixels. Vous trouverez sans peine de telles icnes sur le Web en
tapant  icnes 32x32  dans votre moteur de recherche prfr. Dnissez un dossier
 ressources  et ajoutez-y trois icnes de votre choix.
Vous pouvez galement tlcharger les icnes que j'ai utilises (gure 14.6) pour vous
faciliter la tche, mais rien ne vous empche de crer les vtres.


Tlcharger
les
icnes
B
Code web : 112628


Pour modier l'apparence d'un Tab Bar Item, vous allez utiliser l'inspecteur des attributs.
250

BARRE D'OUTILS

Figure 14.5  L'application comporte trois vues

Figure 14.6  Les icnes que j'ai utilises dans l'application

Comme indiqu la gure 14.7, cliquez sur l'icne Hide or show the Utilities
(1) pour faire apparatre le volet des utilitaires, puis cliquez sur l'icne Show the
Attributes inspector (2). L'inspecteur des attributs tant ach, cliquez sur le Tab
Bar Item de la premire vue (3), et modiez les paramtres Title et Image, sous Bar
Item (4).
Recommencez cette manipulation pour modier les deux autres Tab Bar Item.
Maintenant, il ne vous reste plus qu' insrer le contenu souhait dans les trois vues
pour naliser l'application. Je suis sr que cela ne vous posera aucun problme.
Le code de l'application ne sera pas list ici, car aucun code n'a t crit. Je ne sais
pas ce que vous en pensez, mais moi, je tire mon chapeau aux ingnieurs qui ont conu
cette nouvelle version de Xcode. On peut dire qu'elle facilite vraiment les choses. Ceux
et celles qui ont connu les versions prcdentes ne me contrediront certainement pas !

Barre d'outils
Vous utiliserez un contrle Tool Bar chaque fois qu'il est ncessaire d'ajouter une barre
d'outils dans une application. Ces contrles relvent de la classe UIToolBar. Ils peuvent
tre composs d'un ou de plusieurs boutons rattachs la classe UIBarButtonItem. Ces
boutons peuvent contenir du texte et/ou une image.
251

CHAPITRE 14.

BARRES ET TABULATIONS

Figure 14.7  Il faut utiliser l'inspecteur des attributs pour modier l'apparence d'un
Tab Bar Item

252

BARRE D'OUTILS

Pour vous entraner manipuler les contrles Tool Bar, vous allez dnir une application dans laquelle quatre boutons permettront de changer la couleur et l'alignement
du texte ach dans un Label. la gure 14.8 se trouve le rsultat obtenir.

Figure 14.8  L'application doit ressembler a

Crez une nouvelle application de type Single View Application et donnez-lui le


nom  toolBar . Cliquez sur l'entre MainStoryboard.storyboard dans le volet de
navigation. En utilisant Interface Builder, ajoutez un contrle Tool Bar l'application
et positionnez-le tout en bas de la fentre. Ajoutez trois Bar Button Items au Tool
Bar pour obtenir quelque chose approchant de la gure 14.9.
Double-cliquez successivement sur chacun des quatre Bar Button Items et aectezleur les libells suivants :  Noir ,  Rouge ,  Gauche  et  Centre .
Ajoutez un contrle Label l'application. Aectez-lui le texte  Un simple Label pour
illustrer le fonctionnement du contrle Tool Bar . Redimensionnez ce contrle pour
qu'il tienne sur plusieurs lignes et aectez la valeur 3 au paramtre Lines.
Pour que le code puisse interagir avec les contrles dposs sur l'application, vous allez
dnir des actions et un outlet. Cliquez sur l'icne Show the Assistant Editor et
contrle-glissez-dposez successivement les quatre Bar Button Items juste au-dessus
du @end nal dans le chier d'en-ttes. Dnissez les actions noir, rouge, gauche et
centre.
Dnissez l'outlet leLabel pour le contrle Label.
Le chier ViewController.h doit maintenant ressembler ceci :
253

CHAPITRE 14.

BARRES ET TABULATIONS

Figure 14.9  Positionnez les lments de cette faon


1
2
3
4
5
6
7
8
9
10
11

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
- ( IBAction ) noir :( id ) sender ;
- ( IBAction ) rouge :( id ) sender ;
- ( IBAction ) gauche :( id ) sender ;
- ( IBAction ) centre :( id ) sender ;
@property ( weak , nonatomic ) IBOutlet UILabel * leLabel ;
@end

Il ne reste plus qu' crire quelques lignes de code pour ragir aux appuis sur les Bar
Button Items. Cliquez sur ViewController.m dans le volet de navigation. Reprez les
mthodes action et compltez-les comme ceci :
1
2
3
4
5
6
7
8

- ( IBAction ) noir :( id ) sender {


leLabel . textColor = [ UIColor blackColor ];
}
- ( IBAction ) rouge :( id ) sender {
leLabel . textColor = [ UIColor redColor ];
}

254

BARRE DE RECHERCHE

9
10
11
12
13
14
15

- ( IBAction ) gauche :( id ) sender {


leLabel . textAlignment = UITextAlignmentLeft ;
}
- ( IBAction ) centre :( id ) sender {
leLabel . textAlignment = UITextAlignmentCenter ;
}

Barre de recherche
Le contrle Search Bar est trs pratique lorsqu'il est ncessaire d'eectuer une recherche dans une application. Ce contrle relve de la classe UISearchBar. Je vais vous
montrer comment l'utiliser pour ltrer les donnes aches dans un Table View. la
gure 14.10 se trouve le rsultat obtenir.

Figure 14.10  L'application doit ressembler a

Dnissez une nouvelle application base sur le modle Master-Detail Application


et donnez-lui le nom  searchBar . Cliquez sur MainStoryboard.storyboard dans le
volet de navigation et ajoutez un contrle Search Bar and Search Display Controller
la vue Master, comme indiqu la gure 14.11.
Cliquez sur Show the Assistant editor pour acher cte cte le canevas et le
code MasterViewController.h, dnissez un outlet pour le contrle Table View et
donnez-lui le nom  laListe .
255

CHAPITRE 14.

BARRES ET TABULATIONS

Figure 14.11  Ajoutez un contrle Search


la vue Master

256

Bar and Search Display Controller

BARRE DE RECHERCHE

Dnissez un autre outlet pour le contrle Search Bar et donnez-lui le nom  recherche .
Lors du dveloppement de l'application, vous aurez besoin de trois variables d'instance
de type NSMutableArray. Une pour mmoriser la liste des villes dans sa forme originale
et deux autres pour manipuler la liste ltre. Ajoutez les instructions suivantes dans
l'interface de l'application :
1
2
3

NSMutableArray * maListe ;
NSMutableArray * tampon ;
NSMutableArray * tampon2 ;

Le chier MasterViewController.h doit maintenant ressembler ceci :


1
2
3
4
5
6
7
8
9
10
11
12
13

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
{
NSMutableArray * maListe ;
NSMutableArray * tampon ;
NSMutableArray * tampon2 ;
}
@property ( weak , nonatomic ) IBOutlet UITableViewCell * laListe ;
@property ( weak , nonatomic ) IBOutlet UISearchBar * recherche ;
@end

Pour faire fonctionner cette application, deux tapes sont ncessaires.


1. Ajout de donnes textuelles dans le Table View et sauvegarde dans un objet
NSMutableArray.
2. Filtrage des donnes aches dans le Table View lorsque des informations sont
entres dans le contrle Search Bar.

Initialisation du Table View


D'une faon traditionnelle, l'initialisation du Table View se fera dans la mthode
viewDidLoad du contrleur de vue principal. Cliquez sur MasterViewController.m
dans le volet de navigation et compltez la mthode viewDidLoad comme suit :
1
2
3
4
5
6
7
8
9

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
maListe = [[ NSMutableArray alloc ] init ];
tampon = [[ NSMutableArray alloc ] init ];
[ maListe addObject : @ " Paris " ];
[ maListe addObject : @ " Lyon " ];
[ maListe addObject : @ " Marseille " ];
[ maListe addObject : @ " Toulouse " ];

257

CHAPITRE 14.

10
11
12
13
14
15
16
17
18
19
20
21
22
23

BARRES ET TABULATIONS

[ maListe addObject : @ " Nantes " ];


[ maListe addObject : @ " Nice " ];
[ maListe addObject : @ " Bordeaux " ];
[ maListe addObject : @ " Montpellier " ];
[ maListe addObject : @ " Rennes " ];
[ maListe addObject : @ " Lille " ];
[ maListe addObject : @ " Le Havre " ];
[ maListe addObject : @ " Reims " ];
[ maListe addObject : @ " Le Mans " ];
[ maListe addObject : @ " Dijon " ];
[ maListe addObject : @ " Grenoble " ];
[ maListe addObject : @ " Brest " ];
[ tampon addObjectsFromArray : maListe ];
donn es d ' origine

// M morisation des

Copier ce code
B
Code web : 631625


Les deux premires instructions ajoutes dans cette mthode rservent de l'espace en
mmoire pour les objets NSMutableArray maListe et tampon :
maListe = [[ NSMutableArray alloc ] init ];
tampon = [[ NSMutableArray alloc ] init ];

1
2

Les seize instructions suivantes ajoutent des donnes dans l'objet maListe :
1
2
3

[ maListe addObject : @ " Paris " ];


...
[ maListe addObject : @ " Brest " ];

Enn, la dernire instruction recopie le contenu de l'objet maListe dans l'objet tampon.
Comme son nom le laisse supposer, l'objet tampon sera utilis comme sauvegarde de
l'objet maListe. Nous verrons prochainement pourquoi cette sauvegarde est importante.
Si vous recherchez dans votre mmoire, vous vous rappellerez certainement la technique
permettant de copier les donnes d'un NSMutableArray dans un contrle Table View.
Vous devez dnir les mthodes tableView: tableView numberOfRowsInSection:
section et tableView: tableView cellForRowAtIndexPath: indexPath. La premire dnit le nombre d'lments acher et la seconde dnit chacun des lments
acher.
Insrez le code suivant dans le chier MasterViewController.m :
1
2
3
4
5
6

- ( NSInteger ) tableView :( UITableView *) tableView


numberOfRowsInSection :( NSInteger ) section
{
return [ maListe count ];
}
- ( UITableViewCell *) tableView :( UITableView *) tableView
cellForRowAtIndexPath :( NSIndexPath *) indexPath

258

BARRE DE RECHERCHE

7
8
9
10

UITableViewCell * cell = [ tableView


dequeueReusableCellWithIdentifier : CellIdentifier ];
if ( cell == nil )
{
cell = [[ UITableViewCell alloc ] initWithStyle :
UITableViewCellStyleDefault reuseIdentifier :
CellIdentifier ];
}

11
12
13
14
15
16
17
18
19
20

static NSString * CellIdentifier = @ " Cell " ;

// Configure the cell .


NSString * cellValue = [ maListe objectAtIndex : indexPath . row ];
cell . textLabel . text = cellValue ;
return cell ;

Copier ce code
B
Code web : 160468


Si vous essayez d'excuter l'application, vous obtiendrez une erreur lors de la compilation. Il reste en eet plusieurs petits dtails rgler avant que l'achage des donnes
dans le Table View soit oprationnel.
Comme la gure 14.12, cliquez sur MainStoryboard.storyboard dans le volet de
navigation (1), achez le volet des utilitaires en cliquant sur l'icne Hide or show
the Utilities (2), achez l'inspecteur des attributs en cliquant sur l'icne Show the
Attributes inspector (3), cliquez sur le Table View dans le canevas (4) et choisissez
Dynamic Prototypes dans la liste droulante Content (5).
Le contenu des cellules est en eet dni dans le code, ce qui correspond au modle
Dynamic Prototypes.
Cette correction a produit un avertissement matrialis par un triangle  attention 
de couleur jaune dans la partie suprieure de la fentre de Xcode (1). Cliquez dessus
pour prendre connaissance du problme, puis cliquez sur l'nonc du problme dans
la partie gauche de la fentre (2). Il ne vous reste plus qu' donner un identiant au
prototype pour rgler ce problme (3), comme indiqu la gure 14.13.
Juste histoire de souer un peu, vous pouvez excuter l'application en cliquant sur
Run et constater que le Table View contient des donnes.

Filtrage des donnes aches dans le Table View


Lorsque le contenu du contrle Search Bar change, la mthode searchBar: searchBar
est excute. Nous allons donc utiliser cette mthode
pour ltrer les donnes aches dans le Table View.
Mais avant de plonger dans le code, je vous rappelle que :
textDidChange: searchText

259

CHAPITRE 14.

BARRES ET TABULATIONS

Figure 14.12  Choisissez Dynamic

Prototypes

dans la liste droulante Content

Figure 14.13  Donnez un identiant au prototype pour rgler le problme

260

BARRE DE RECHERCHE

 les donnes aches dans le Table View proviennent du NSMutableArray maListe ;


 le NSMutableArray maListe a t sauvegard dans l'objet tampon la n de la
mthode viewDidLoad.
Ajoutez le code suivant dans le chier MasterViewController.m :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

- ( void ) searchBar :( UISearchBar *) searchBar textDidChange :(


NSString *) searchText
{
tampon2 = [[ NSMutableArray alloc ] init ];
[ tampon2 addObjectsFromArray : tampon ];
[ maListe removeAllObjects ];
if ([ searchText isEqualToString : @ " " ])
{
[ maListe removeAllObjects ];
[ maListe addObjectsFromArray : tampon ]; // Restitution des
donn es originales
return ;
}

for ( NSString * name in tampon2 )


{
NSRange r = [ name rangeOfString : searchText ];
if ( r . location != NSNotFound )
{
if ( r . location == 0 )
[ maListe addObject : name ];
}
}

Copier ce code
B
Code web : 763064


Ne vous laissez pas impressionner par la longueur de cette mthode ! Elle ne contient
qu'un peu de logique lmentaire que nous allons facilement dcortiquer. La ligne 3
instancie l'objet tampon2. En d'autres termes, elle rserve la mmoire pour cet objet :
1

tampon2 = [[ NSMutableArray alloc ] init ];

La ligne 4 recopie le contenu de l'objet tampon dans l'objet tampon2 :


1

[ tampon2 addObjectsFromArray : tampon ];

La ligne 5 supprime le contenu de l'objet maListe :


1

[ maListe removeAllObjects ];

Les instructions contenues dans le if suivant (lignes 6 11) sont excutes lorsque la
zone de recherche devient vide. Ce cas se produit lorsque l'utilisateur eace le texte
qu'il a prcdemment tap.
Lorsque la zone de recherche ne contient plus aucun texte, la liste originale doit tre
restaure dans le Table View. Pour cela, on commence par eacer son contenu :
261

CHAPITRE 14.

BARRES ET TABULATIONS

[ maListe removeAllObjects ];

Puis l'objet tampon (qui contient les donnes originales) est ensuite copi dans l'objet
:

maListe
1

[ maListe addObjectsFromArray : tampon ];

Il n'est pas ncessaire d'excuter les instructions suivantes. C'est pourquoi une instruction return met n la mthode.
L'instruction for de la ligne 13 passe en revue toutes les donnes contenues dans l'objet
tampon2 :
1

for ( NSString * name in tampon2 )

La ligne 15 dnit l'objet NSRange r et l'initialise avec la premire occurrence du texte


tap dans la zone de recherche dans l'objet tampon2 :
NSRange r = [ name rangeOfString : searchText ];

Si le texte tap dans la zone de recherche fait partie de l'lment examin dans tampon2 :
1

if ( r . location != NSNotFound )

Et si ce texte se trouve au dbut de l'lment examin :


1

if ( r . location == 0 )

L'lment trouv est ajout au NSMutableArray


1

maListe

[ maListe addObject : name ];

La boucle for examine tour tour tous les lments de l'objet maListe. En n de
boucle, tous les lments qui commencent par le texte tap dans la zone de recherche
sont donc copis dans l'objet maListe.
Aprs autant de lignes de code, vous brlez certainement d'envie de lancer l'application.
Cliquez sur Run et protez de votre application. Vous l'avez bien mrit.
Telle qu'elle a t implmente dans cet exemple, la recherche est sensible
la casse des caractres. Ainsi par exemple, si vous tapez la lettre  l  dans
la zone de recherche, aucun rsultat ne sera ach dans le Table View. Par
contre, si vous tapez  L , les villes Lyon, Lille, Le Havre et Le Mans seront
aches.

Copier le code
B
Code web : 457355

Gestion simultane de deux vues sur un iPad


Le modle Master-Detail Application est particulirement bien adapt aux iPad.
Leur surface d'achage, bien plus grande que celle oerte par les iPhone et iPod Touch,
262

GESTION SIMULTANE DE DEUX VUES SUR UN IPAD

permet aux applications bases sur ce modle de rassembler deux vues : une liste et
une vue dtaille de l'lment slectionn dans la liste. L'application iPad Mail (gure
14.14) est un parfait exemple d'utilisation de ce modle.

Figure 14.14  L'application Mail sur iPad

Et maintenant, passons sans plus attendre la pratique. Dnissez une nouvelle application base sur le modle Master-Detail Application, donnez-lui le nom  masterDetail  et choisissez iPad dans la liste droulante Device Family.
Cliquez sur MainStoryboard.storyboard dans le volet de navigation et observez les
nombreux objets qui ont t crs, visibles la gure 14.15.
Comme vous pouvez le voir, l'application contient :
 un contrleur de vue Split View ;
 un contrleur de navigation et un Table View lis au Master View Controller ;
 un contrleur de navigation et un contrleur de vue dtaille.
Excutez l'application en cliquant sur l'icne Run. La gure 14.16 reprsente le rsultat
obtenu en mode portrait et en mode paysage. Pas si mal pour un dbut !
La vue Master consiste en un contrle Table View. La vue Detail reprsente les dtails
de l'lment slectionn dans la vue master.
Je sens que vous avez envie de vous dgourdir les doigts. a tombe bien, nous allons
personnaliser l'application qui vient d'tre gnre par Xcode pour qu'elle ache trois
lments dans la liste et qu'un clic sur l'un d'entre eux provoque l'achage d'une image
et d'un texte dans la vue dtaille. la gure 14.17 se trouve le rsultat obtenir.
Pour arriver ce rsultat, voici les tapes accomplir :
1. suppression du texte ach dans la vue dtaille au lancement de l'application ;
263

CHAPITRE 14.

BARRES ET TABULATIONS

Figure 14.15  De nombreux objets ont t crs

Figure 14.16  L'application en mode portrait et en mode paysage sur un iPad

264

GESTION SIMULTANE DE DEUX VUES SUR UN IPAD

Figure 14.17  Notre application ressemblera a

2. modication du texte ach dans la barre d'outils ;


3. dnition des entres textuelles du contrle Table View ;
4. ajout de trois images dans les ressources de l'application et d'un contrle Image
View dans la vue dtaille ;
5. dans la vue dtaille, achage de l'image et du texte correspondant l'entre
clique dans le contrle Table View.
Commenons par supprimer le texte ach dans la vue dtaille au lancement de l'application. Cette tape est trs simple : cliquez sur l'entre MainStoryboard.storyboard
dans le volet de navigation.
Reprez
le Label dans la vue Detail, cliquez dessus puis


appuyez sur la touche Suppr du clavier pour le supprimer.
Nous allons maintenant modier le texte ach dans la barre d'outils. Cliquez sur
DetailViewController.m dans le volet de navigation. Reprez la mthode suivante :
1

splitViewController : willHideViewController : withBarButtonItem :


forPopoverController :

. . . et modiez sa premire instruction comme suit :


1

barButtonItem . title = @ " vous de choisir " ;

Nous en sommes dj la troisime tape, savoir, la dnition des entres aches


dans le contrle Table View. Nous allons pour cela utiliser la mthode viewDidLoad
du chier MasterViewController.m. Cliquez sur ce chier dans le volet de navigation
et compltez la mthode viewDidLoad comme suit :
1
2
3
4
5

- ( void ) viewDidLoad
{
laListe = [[ NSMutableArray alloc ] init ];
[ laListe addObject : @ " Chat " ];
[ laListe addObject : @ " Chien " ];

265

CHAPITRE 14.

6
7
8
9
10
11
12

BARRES ET TABULATIONS

[ laListe addObject : @ " Cheval " ];


self . navigationItem . title = @ " Choisissez un animal " ;

[ super viewDidLoad ];
self . clearsSelectionOnViewWillAppear = NO ;
self . contentSizeForViewInPopover = CGSizeMake ( 320 .0 , 600 . 0 );

La premire instruction initialise le NSMutableArray

laListe

laListe = [[ NSMutableArray alloc ] init ];

Les trois instructions suivantes ajoutent trois entres dans le tableau laListe :
1
2
3

[ laListe addObject : @ " Chat " ];


[ laListe addObject : @ " Chien " ];
[ laListe addObject : @ " Cheval " ];

Enn, la dernire instruction ajoute dnit le titre qui sera ach dans la fentre
popup :
1

self . navigationItem . title = @ " Choisissez un animal " ;

L'objet laListe a t initialis dans la mthode viewDidLoad, mais il n'a pas t


dni. Pour rparer cette lacune, cliquez sur MasterViewController.h dans le volet
de navigation, puis ajoutez les lignes 2 4 sous la dnition de l'interface :
1
2
3
4

@interface MasterViewController : UITableViewController


{
NSMutableArray * laListe ;
}

Pour acher les donnes dans le Table View, vous devez encore insrer deux mthodes
dans le chier MasterViewController.m :
1
2
3
4
5
6
7
8
9
10

- ( NSInteger ) tableView :( UITableView *) tableView


numberOfRowsInSection :( NSInteger ) section
{
return [ laListe count ];
}
- ( UITableViewCell *) tableView :( UITableView *) tableView
cellForRowAtIndexPath :( NSIndexPath *) indexPath
{
static NSString * MyIdentifier = @ " MyIdentifier " ;

11
12
13

266

UITableViewCell * cell = [ tableView


dequeueReusableCellWithIdentifier : MyIdentifier ];
if ( cell == nil )
cell = [[ UITableViewCell alloc ] initWithStyle :
UITableViewCellStyleDefault reuseIdentifier : MyIdentifier
];

GESTION SIMULTANE DE DEUX VUES SUR UN IPAD

14
15
16
17
18
19

// Configuration de la cellule
NSString * cellValue = [ laListe objectAtIndex : indexPath . row ];
cell . textLabel . text = cellValue ;
return cell ;

Copier ce code
Code web : 196214


Attention, si vous essayez d'excuter l'application, vous obtiendrez une erreur lors de
la compilation. Il reste en eet plusieurs petits dtails rgler avant que l'achage des
donnes dans le Table View soit oprationnel :
 le contenu des cellules tant dni dans le code, il faut utiliser un Dynamic Prototypes ;
 un identiant doit tre aect au prototype.
Vous pouvez ds maintenant excuter l'application et vrier que le Table View ache
bien les trois cellules qui ont t renseignes.
Maintenant, ajoutez trois images dans les ressources de l'application. Si vous voulez
utiliser les mmes images que moi, vous pouvez les tlcharger en utilisant le code web
suivant.


Tlcharger
les
images
B
Code web : 760903


Ensuite, cliquez sur l'entre MainStoryboard.storyboard dans le volet de navigation.
Reprez la vue Detail et ajoutez-y un contrle Image View et un contrle Label.
Redimensionnez et repositionnez ces contrles an d'obtenir quelque chose comme la
gure 14.18.
Dnissez l'outlet uneImage pour le contrle Image View et l'outlet laLegende pour
le contrle Label. Ces oprations doivent maintenant vous tre familires. Au besoin,
reportez-vous aux chapitres prcdents pour avoir plus de dtails sur la technique
utiliser.
L'application est presque termine : il ne reste plus que la cinquime tape, l'achage de
l'image et du texte qui correspondent l'lment choisi par l'utilisateur dans le Table
View. Avant tout, vous devez dterminer quel lment a t choisi par l'utilisateur
en dnissant la mthode didSelectRowAtIndexPath dans la vue Master. Cliquez sur
MasterViewController.m et dnissez la mthode didSelectRowAtIndexPath comme
suit :
B

1
2
3
4

- ( void ) tableView :( UITableView *) tableView


didSelectRowAtIndexPath :( NSIndexPath *) indexPath
{
self . detailViewController . detailItem = [ NSString
stringWithFormat : @ " % @ " , [ laListe objectAtIndex : indexPath
. row ]];
}

267

CHAPITRE 14.

BARRES ET TABULATIONS

Figure 14.18  Placez les contrles comme ceci

268

GESTION SIMULTANE DE DEUX VUES SUR UN IPAD

L'unique instruction de cette mthode rcupre l'lment choisi, le convertit en un


NSString et le stocke dans la variable detailItem de la vue dtaille.
Il ne reste plus qu' rcuprer la donne passe dans la vue dtaille et acher
l'image et le texte correspondants. Cela se fera dans la mthode configureView de la
vue Detail. Cliquez sur DetailViewController.m dans le volet de navigation. Reprez
la mthode configureView et compltez-la comme suit :
1
2
3
4
5

- ( void ) configureView
{
self . laLegende . text = [ self . detailItem description ];
self . uneImage . image = [ UIImage imageNamed :[ NSString
stringWithFormat : @ " % @ % @ " ,[ self . detailItem description ] , @ " .
jpg " ]];
}

Cette mthode est galement trs courte.


La ligne 3 rcupre la chane stocke dans l'objet detailItem. Cette chane est aecte
la proprit texte du Label laLegende, ce qui provoque son achage dans la vue
dtaille.
La ligne 4 vous semble peut-tre un peu complique. Cela vient de l'imbrication de
trois messages dans la deuxime partie de l'instruction. N'ayez crainte, il n'y a rien
d'insurmontable dans cette instruction. Pour bien comprendre ce qui se passe, il faut
toujours partir du message le plus interne. Ici :
1

[ self . detailItem description ]

Ce message a dj t utilis dans l'instruction prcdente. Il renvoie la version texte


du contenu de l'objet detailItem. Jusque-l, tout va bien !
Passons au message qui engloble [self.detailItem description] :
1

[ NSString stringWithFormat : @ " % @% @ " ,[ self . detailItem description


] , @ " . jpg " ]

Ce message cre un objet NSString en concatnant la valeur slectionne par l'utilisateur et la chane  .jpg . Supposons que l'utilisateur choisisse  chat  dans le Table
View. Ce message produira un NSString contenant la chane  chat.jpg .
Passons enn au troisime message :
1

[ UIImage imageNamed : ...]

Ce message dnit un objet UIImage en piochant dans les ressources de l'application. Le


chier slectionn est prcisment celui dont le nom a t calcul l'tape prcdente.
Pour rsumer, ces trois messages imbriqus fabriquent un objet UIImage dont le nom
est gal au contenu de la cellule slectionne par l'utilisateur, auquel on ajoute  .jpg .
Vous voyez, tout cela est trs simple
Ah oui, j'allais oublier l'essentiel : une fois l'objet UIImage obtenu, il est aect la proprit image du contrle Image View (self.uneImage.image = ...). Ainsi, l'image
est ache dans la vue Detail.
269

CHAPITRE 14.

BARRES ET TABULATIONS

Il ne vous reste plus qu' cliquer sur Run et proter du rsultat (gure 14.19).

Figure 14.19  L'application est termine et fonctionne

Vous pouvez copier les codes de l'application grce au code web suivant.


Copier ce code
B
Code web : 814981

En rsum
 Les contrles Tab Bar permettent de crer facilement des applications multivues.
L'utilisateur passe d'une vue l'autre en cliquant sur les icnes du contrle Tab
Bar, rattachs la classe UITabBar.
 Le modle Master-Detail Application est particulirement bien adapt aux iPad.
Leur surface d'achage, bien plus grande que celle des iPhone et iPod Touch, permet
aux applications bases sur ce modle de rassembler deux vues : une liste et une vue
dtaille de l'lment slectionn dans la liste.
 Vous utiliserez un contrle Tool Bar chaque fois qu'il est ncessaire d'ajouter une
barre d'outils dans une application. Les contrles Tool Bar relvent de la classe
UIToolBar. Ils peuvent tre composs d'un ou de plusieurs boutons rattachs la
classe UIBarButtonItem. Ces boutons peuvent contenir du texte et/ou une image.
 Le contrle Search Bar est trs pratique lorsqu'il est ncessaire d'eectuer une recherche dans une application. Ce contrle relve de la classe UISearchBar.

270

Chapitre

15

Insertion de contrles avec le code


Dicult :

our insrer des contrles dans une vue, la solution la plus immdiate consiste
utiliser Interface Builder. Si vous vous sentez l'me codeuse, cette section devrait
vous intresser puisque nous allons voir comment insrer des contrles dans une vue
en utilisant le langage Objective-C.
Les techniques exposes dans ce chapitre ont un autre avantage : elles permettent d'ajouter
des contrles pendant l'excution de l'application. Cela peut s'avrer utile si vous devez
crer une application qui s'adapte son heure d'excution, la vitesse du device, ou je
ne sais quelle autre variable qu'il n'est pas possible de prvoir dans le storyboard.

271

CHAPITRE 15.

INSERTION DE CONTRLES AVEC LE CODE

Dans un premier temps, je vais vous donner un code complet, que vous pourrez copier
grce un code web. Dans un second temps, je vais vous expliquer ce code. Il n'y aura
rien de compliqu, rassurez-vous.

Le code complet
Dnissez un nouveau projet bas sur le modle Single View Application et donnezlui le nom  defControles . Cliquez sur defControlesViewController.m dans le volet de
navigation et compltez la mthode viewDidLoad comme suit :
1
2
3
4
5
6
7
8
9
10
11

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
// Ajout d 'un Label
CGRect rectLab = CGRectMake ( 10 , 10 , 100 , 20 ) ; // D finition d 'un
rectangle
UILabel * monLabel = [[ UILabel alloc ] initWithFrame : rectLab ];
monLabel . text = @ " Ceci est un label " ;
[ self . view addSubview : monLabel ];

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

272

// Ajout d 'un Round Rect Button


UIButton * monBouton = [ UIButton buttonWithType :
UIButtonTypeRoundedRect ];
monBouton . frame = CGRectMake (10 , 40 , 100 , 20 ) ;
[ monBouton setTitle : @ " Un bouton " forState :
UIControlStateNormal ];
[ self . view addSubview : monBouton ];
// Ajout d 'un Text Field
CGRect rectTF = CGRectMake ( 10 , 70 , 100 , 20 ) ; // D finition d ' un
rectangle
UITextField * monChampTexte = [[ UITextField alloc ]
initWithFrame : rectTF ];
monChampTexte . borderStyle = UITextBorderStyleLine ;
[ self . view addSubview : monChampTexte ];
// Ajout d 'un rectangle rouge
CGRect rectangle = CGRectMake ( 10 , 100 , 100 , 100 ) ; // D finition
d ' un rectangle
UIView * subview = [[ UIView alloc ] initWithFrame : rectangle ];
// Ajout de la vue correspondante
subview . backgroundColor = [ UIColor redColor ];
[ self . view addSubview : subview ];
// Ajout d 'un Image View
UIImage * img = [ UIImage imageWithContentsOfFile : [[ NSBundle
mainBundle ] pathForResource : @ " petitchat " ofType : @ " jpg " ]];
CGRect cropRect = CGRectMake (0 , 0 , 160 , 240 ) ;

LE CODE COMPLET

32
33
34
35
36
37

CGImageRef imageRef = CGImageCreateWithImageInRect ([ img


CGImage ] , cropRect ) ;
UIImageView * monImage = [[ UIImageView alloc ] initWithFrame :
CGRectMake ( 150 , 10 , 160 , 240 ) ];
monImage . image = [ UIImage imageWithCGImage : imageRef ];
[ self . view addSubview : monImage ];
CGImageRelease ( imageRef ) ;

Copier ce code
Code web : 312856


Pour terminer, dnissez le groupe  Resources  dans l'arborescence de l'application et
ajoutez-y une image de 160 x 240 pixels que vous nommerez  petitchat.jpg . L'image
que j'ai utilise se trouve la gure 15.1.
B

Figure 15.1   petitchat.jpg 


Tlcharger l'image
Code web : 303133


Nous n'avons pas fait appel Interface Builder et pourtant. . . Lancez l'application en
cliquant sur l'icne Run. L'application reprsente la gure 15.2 se lance.
Intressant, non ?
Dans la suite de ce chapitre, je vais vous montrer ce qui se cache dans le code et
pourquoi plusieurs contrles apparaissent dans la vue de l'application. Le code est
clairement dcoup en plusieurs blocs indpendants. Chacun d'entre eux est responsable
de l'achage d'un contrle dans la vue.
B

273

CHAPITRE 15.

INSERTION DE CONTRLES AVEC LE CODE

Figure 15.2  Cette application a t cre uniquement avec du code

Achage d'un Label


Je pense qu'arrivs ce stade, vous savez tous quoi ressemble un Label. Eh bien
voici le code responsable de la dnition et de l'achage d'un Label :
1
2
3
4

CGRect rectLab = CGRectMake ( 10 , 10 , 200 , 20 ) ;


UILabel * monLabel = [[ UILabel alloc ] initWithFrame : rectLab ];
monLabel . text = @ " Ceci est un label " ;
[ self . view addSubview : monLabel ];

Avant de dnir le Label, il est ncessaire de choisir son emplacement (10,


dimensions (200,20). Ceci se fait en crant une structure de type CGRect :
1

10)

et ses

CGRect rectLab = CGRectMake ( 10 , 10 , 200 , 20 ) ;

Mais quoi correspondent ces nombres ?

Le premier nombre correspond l'abscisse du coin suprieur gauche du contrle, le


deuxime l'ordonne du coin suprieur gauche du contrle, le troisime la largeur
du contrle et le quatrime la hauteur du contrle. Regardez la gure 15.3, vous
devriez comprendre.
274

AFFICHAGE D'UN

LABEL

Figure 15.3  Correspondance des valeurs dnies dans le code

Le Label peut maintenant tre dni. Nous lui donnons le nom rectLab et nous utilisons les coordonnes prcises dans la structure rectLab pour le positionner et le
dimensionner :
1

UILabel * monLabel = [[ UILabel alloc ] initWithFrame : rectLab ];

Le texte ach dans le Label est dni avec la proprit text :


1

monLabel . text = @ " Ceci est un label " ;

Il ne reste plus qu' ajouter le label (addSubView:


(self.view) pour provoquer son achage :
1

monLabel)

la vue courante

[ self . view addSubview : monLabel ];

Dans cet exemple, la proprit text a t utilise pour dnir le texte ach
dans le Label. De nombreuses autres proprits existent. Pour en avoir la
liste, le plus simple consiste faire appel la documentation Apple. Vous
pouvez vous aider de la gure 15.4 pour la marche suivre : cliquez sur
UILabel dans le code (1), achez la section Aide rapide dans le volet
des utilitaires en cliquant sur l'icne Show Quick Help (2), puis cliquez sur
UILabel dans la section d'aide rapide (3).

275

CHAPITRE 15.

INSERTION DE CONTRLES AVEC LE CODE

Figure 15.4  Achage de la documentation d'Apple

La fentre d'aide donne de trs nombreuses informations. En particulier, elle liste les
proprits de la classe et leurs modes d'accs.

Achage d'un Round Rect Button


Un Round

Rect Button

ressemble la gure 15.5.

Figure 15.5  Un Round

Rect Button

Et voici le code responsable de la dnition et de l'achage du Round


1
2
3
4

Rect Button

UIButton * monBouton = [ UIButton buttonWithType :


UIButtonTypeRoundedRect ];
monBouton . frame = CGRectMake (10 , 40 , 100 , 20 ) ;
[ monBouton setTitle : @ " Un bouton " forState : UIControlStateNormal
];
[ self . view addSubview : monBouton ];

Dans un premier temps, l'objet UIButton


1

276

monBouton

est instanci :

UIButton * monBouton = [ UIButton buttonWithType :


UIButtonTypeRoundedRect ];

AFFICHAGE D'UN

Son emplacement (10,


ment pour le Label.
1

40)

et sa taille (100,

20)

TEXT FIELD

sont alors dnis, comme prcdem-

monBouton . frame = CGRectMake ( 10 , 40 , 100 , 20 ) ;

Le texte ach dans le bouton l'tat  normal  (c'est--dire non press et non
dsactiv) est alors dni :
1

[ monBouton setTitle : @ " Un bouton " forState : UIControlStateNormal


];

Puis le bouton est ajout la vue :


1

[ self . view addSubview : monBouton ];

Plusieurs autres proprits, telles que le type du bouton, la couleur du texte, l'image
ache dans le bouton, etc. sont accessibles dans le code. Vous en saurez plus en
consultant la documentation Apple sur la classe UIButton.

Achage d'un Text Field


Un Text

Field

ressemble la gure 15.6.

Figure 15.6  Un Text

Field

Et voici le code responsable de la dnition et de l'achage de ce Text


1
2
3
4

CGRect rectTF = CGRectMake ( 10 , 70 , 100 , 20 ) ; // D finition d 'un


rectangle
UITextField * monChampTexte = [[ UITextField alloc ] initWithFrame
: rectTF ];
monChampTexte . borderStyle = UITextBorderStyleLine ;
[ self . view addSubview : monChampTexte ];

Dans un premier temps, la position (10, 70) et les dimensions (100,


de texte sont dnies dans une structure CGRect :
1

Field

20)

de la zone

CGRect rectTF = CGRectMake ( 10 , 70 , 100 , 20 ) ;

Les paramtres de la fonction CGRectMake() sont les mmes que dans les
deux sous-parties prcdentes, relatives aux contrles Label et Round Rect
Button.

La zone de texte est alors instancie :


1

UITextField * monChampTexte = [[ UITextField alloc ] initWithFrame


: rectTF ];

277

CHAPITRE 15.

INSERTION DE CONTRLES AVEC LE CODE

Pour qu'elle soit bien visible, on lui aecte une bordure :


monChampTexte . borderStyle = UITextBorderStyleLine ;

Puis la zone de texte est ajoute la vue :


1

[ self . view addSubview : monChampTexte ];

Consultez la documentation Apple pour savoir quelles proprits sont accessibles pour
les contrles UITextField.

Achage d'un rectangle de couleur rouge


Voici le code qui permet de dnir et d'acher un rectangle 1 de couleur rouge :
1
2
3
4

CGRect rectangle = CGRectMake ( 10 , 100 , 100 , 100 ) ; // D finition d '


un rectangle
UIView * subview = [[ UIView alloc ] initWithFrame : rectangle ]; //
Ajout de la vue correspondante
subview . backgroundColor = [ UIColor redColor ];
[ self . view addSubview : subview ];

Dans un premier temps, la position (10, 100) et les dimensions (100,


tangle sont dnies dans une structure CGRect :

100)

du rec-

CGRect rectangle = CGRectMake ( 10 , 100 , 100 , 100 ) ;

L'instruction suivante instancie un objet UIView dont les dimensions ont t spcies
dans le CGRect rectangle :
UIView * subview = [[ UIView alloc ] initWithFrame : rectangle ];

Pour que le rectangle soit bien visible dans la vue, nous lui aectons une couleur
d'arrire-plan rouge en initialisant sa proprit backgroundColor :
subview . backgroundColor = [ UIColor redColor ];

Il ne reste plus qu' ajouter le rectangle la vue courante :


1

[ self . view addSubview : subview ];

Encore une fois, je vous invite consulter la documentation Apple sur la classe UIView
pour prendre connaissance des proprits et mthodes utilisables.

Achage d'une image


Voici le code permettant la dnition et l'achage d'une image :
1. En l'occurrence, il s'agit d'un carr, mais ne chipotons pas.

278

AFFICHAGE D'UNE IMAGE

1
2
3
4
5
6
7

UIImage * img = [ UIImage imageWithContentsOfFile : [[ NSBundle


mainBundle ] pathForResource : @ " petitchat " ofType : @ " jpg " ]];
CGRect cropRect = CGRectMake (0 , 0 , 160 , 240 ) ;
CGImageRef imageRef = CGImageCreateWithImageInRect ([ img CGImage
] , cropRect ) ;
UIImageView * monImage = [[ UIImageView alloc ] initWithFrame :
CGRectMake ( 150 , 10 , 160 , 240 ) ];
monImage . image = [ UIImage imageWithCGImage : imageRef ];
[ self . view addSubview : monImage ];
CGImageRelease ( imageRef ) ;

Copier ce code
B
Code web : 569809

L'image acher doit avoir t pralablement place dans les ressources de


l'application. Je ne vous dis pas comment faire, vous devriez le savoir.

Le code utilis pour acher une image est lgrement plus complexe que les prcdents.
Ceci est d au fait que l'achage d'une image ncessite un plus grand nombre d'tapes.
1. Cration d'un objet UIImage, puis stockage de l'image dans cet objet.
2. Dnition d'un objet UIImageView.
3. Dnition d'une structure CGImageRef pour regrouper les informations relatives
l'image.
4. Aectation de l'objet CGImageRef l'UIImageView.
5. Ajout de l'Image View la vue courante.
La premire instruction dnit l'objet UIImage img et l'initialise avec l'image  petitchat.jpg  :
1

UIImage * img = [ UIImage imageWithContentsOfFile : [[ NSBundle


mainBundle ] pathForResource : @ " petitchat " ofType : @ " jpg " ]];

Pour acher une image, vous devez utiliser un Image View. L'instruction suivante
dnit l'objet UIImageView monImage, ainsi que sa position (150, 10) et ses dimensions
(160, 240) :
1

UIImageView * monImage = [[ UIImageView alloc ] initWithFrame :


CGRectMake ( 150 , 10 , 160 , 240 ) ];

Pour initialiser l'objet Image View qui vient d'tre instanci, vous devez dnir ses
dimensions dans une structure CGRect :
1

CGRect cropRect = CGRectMake (0 , 0 , 160 , 240 ) ;

Puis utiliser ces dimensions et l'objet UIImage prcdemment cr pour dnir une
structure CGImageRef :
279

CHAPITRE 15.

INSERTION DE CONTRLES AVEC LE CODE

CGImageRef imageRef = CGImageCreateWithImageInRect ([ img CGImage


] , cropRect ) ;

Il ne reste plus qu' aecter la structure CGImageRef la proprit image de l'Image


View :
monImage . image = [ UIImage imageWithCGImage : imageRef ];

Et ajouter cet Image


1

View

la vue courante :

[ self . view addSubview : monImage ];

La dernire instruction supprime l'objet CGImageRef de la mmoire. Une fois l'image


ache, celui-ci n'a en eet plus aucun intrt :
1

CGImageRelease ( imageRef );

Une fois encore, je vous invite consulter la documentation Apple pour prendre connaissance des proprits des objets UIImage et UIImageView, et donc pour avoir un aperu
de ce qu'il est possible de faire avec ces objets.

En rsum
Pour insrer des contrles dans une vue, la solution la plus immdiate consiste utiliser
Interface Builder. Mais si vous vous sentez l'me codeuse, vous pouvez utiliser du code
pour parvenir au mme rsultat. Vous pouvez crer les contrles suivants :
 Label ;
 Round Rect Button ;
 Text Field ;
 rectangles ;
 Image View.

280

Chapitre

16

TP : Un navigateur Web trs cibl


Dicult :

ette partie a t trs riche et je suis sr que vous avez fait de srieux progrs en programmation Objective-C. C'est pourquoi je vous propose de naviguer en solo (rassurezvous, je ne serai pas trs loin) pour crer une application partir d'une ide et de rien
d'autre !
Je ne sais pas si vous utilisez votre iPod Touch/iPhone/iPad pour naviguer sur le Web.
Personnellement, cela m'arrive frquemment, et je me rends compte que je vais toujours
sur les mmes sites. Pour faciliter l'accs vos sites prfrs, pourquoi ne pas crer une
application dans laquelle il vous surait de cliquer sur un lment dans une liste pour
accder au site correspondant ?

281

CHAPITRE 16.

TP : UN NAVIGATEUR WEB TRS CIBL

Principe du TP
Ce TP est tout fait votre porte si vous avez parcouru les chapitres de la troisime
partie. Au besoin, n'hsitez pas vous reporter certains passages pour avoir des pistes
lorsque vous dvelopperez ce projet.
Mais avant toute chose, je vous propose de vous montrer quoi ressemblera notre
application. Pour vous faire une ide, regardez la gure 16.1.

Figure 16.1  Voici quoi ressemblera notre application

a vous tente ? Alors, voici quelques conseils qui devraient bien dbroussailler le terrain.
Je vais volontairement tre bref pour vous montrer que vous pouvez raliser de grandes
choses. . . facilement !
Bien sr, il est tout fait possible de crer cette application partir du modle Single
View Application, mais il semble plus judicieux et plus facile d'utiliser le modle
Master-Detail Application. En eet, si le modle Single View Application est
en quelque sorte  universel , puisqu'il permet de raliser toutes sortes d'applications,
le modle Master-Detail Application vous pargnera une partie du travail en prdnissant les deux vues de l'application. Il vous sura donc de les complter en y
ajoutant les contrles et les contenus ncessaires.
Vous serez amens crer une vue dtaille dans laquelle vous placerez un contrle Web
View. Pour que la vue principale communique l'adresse du site choisi par l'utilisateur
la vue dtaille, vous devrez crer une variable d'instance. Par exemple dans la classe
de la vue dtaille, et vous arranger pour que la vue principale puisse accder cette
variable.
Et maintenant, c'est vous de jouer !
282

CORRECTION

Correction
J'espre que vous n'avez pas eu trop de problmes en dveloppant cette application. Si
vous n'avez rencontr aucune dicult, je vous tire mon chapeau. Dans le cas contraire,
je vous rassure, c'est tout fait normal : le langage Objective-C est capricieux et les
messages d'aide ne sont pas toujours explicites (du moins pour un nophyte). Il n'est
pas rare de passer des heures sur une erreur qui, nalement, tait tout autre que celle
laquelle on pensait de prime abord !
Je vais vous accompagner par tapes dans la correction de ce TP et vous verrez que ce
n'tait pas si complexe que a.

Dnition de l'application et de la vue secondaire


Dnissez une nouvelle application de type Master-Detail Application et donnez-lui
le nom  favoris . Comme le montre le canevas MainStoryboard.storyboard (gure
16.2), cette simple opration a cr une vue Master et une vue Detail.

Figure 16.2  Une vue Master et une vue Detail ont t automatiquement cres

Dnition des favoris


Les sites favoris seront achs dans la vue Master. Le but est d'obtenir le rsultat
visible la gure 16.3.
Voici les informations qui correspondent aux sites Web que j'ai choisis :
 Google : http://www.google.fr
 Le Site du Zro : http://www.siteduzero.com
 Mediaforma : http://www.mediaforma.com
Bien entendu, rien ne vous empche de choisir d'autres sites Web ou de complter la
liste comme vous l'entendez.
283

CHAPITRE 16.

TP : UN NAVIGATEUR WEB TRS CIBL

Figure 16.3  Les sites favoris sont achs dans la vue Master

Les donnes de la vue Master seront directement dnies dans le code. Cliquez sur
MasterViewController.m dans le volet de navigation an de complter la mthode
ViewDidLoad comme suit :
1
2
3
4
5
6
7
8
9
10
11
12
13
14

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
mesFavoris = [[ NSMutableArray alloc ] init ];
[ mesFavoris addObject : @ " Google " ];
[ mesFavoris addObject : @ " Le Site du Z ro " ];
[ mesFavoris addObject : @ " Mediaforma " ];
self . navigationItem . title = @ " Mes sites Web pr f r s " ;

adressesWeb = [[ NSMutableArray alloc ] init ];


[ adressesWeb addObject : @ " http :// www . google . fr " ];
[ adressesWeb addObject : @ " http :// www . siteduzero . com " ];
[ adressesWeb addObject : @ " http :// www . mediaforma . com " ];

Le premier bloc d'instructions (lignes 4 8) dnit les lments qui seront achs dans
le contrle Table View. Dans un premier temps, un espace mmoire est rserv pour
l'objet NSMutableArray mesFavoris :
1

284

mesFavoris = [[ NSMutableArray alloc ] init ];

CORRECTION

Les lignes 5 7 dnissent les trois noms de sites achs dans le Table
1
2
3

View

[ mesFavoris addObject : @ " Google " ];


[ mesFavoris addObject : @ " Le Site du Z ro " ];
[ mesFavoris addObject : @ " Mediaforma " ];

L'instruction de la ligne 8 dnit le titre qui sera ach dans la partie suprieure du
Table View :
1

self . navigationItem . title = @ " Mes sites Web pr f r s " ;

Le bloc d'instructions suivant (lignes 10 13) initialise un autre NSArray dans lequel
seront stockes les adresses URL qui correspondent aux sites achs dans le Table
View. La premire instruction rserve de l'espace en mmoire pour accueillir l'objet
NSArray adressesWeb :
1

adressesWeb = [[ NSMutableArray alloc ] init ];

Les trois instructions suivantes dnissent les adresses des trois sites favoris :
1
2
3

[ adressesWeb addObject : @ " http :// www . google . fr " ];


[ adressesWeb addObject : @ " http :// www . siteduzero . com " ];
[ adressesWeb addObject : @ " http :// www . mediaforma . com " ];

Pour que cette mthode fonctionne, vous devez dclarer les variables mesFavoris et
dans le chier d'en-ttes. Cliquez sur MasterViewController.h dans le
volet de navigation et dnissez les deux variables d'instance :
adressesWeb
1
2
3
4
5
6
7
8
9

# import < UIKit / UIKit .h >


@interface MasterViewController : UITableViewController
{
NSMutableArray * mesFavoris ;
NSMutableArray * adressesWeb ;
}
@end

Si vous avez des souvenirs du chapitre 11 consacr aux informations tabulaires (page
197), vous savez que la dnition du NSArray ne sut pas. Vous devez galement le
relier au Table View pour que les donnes s'achent. Pour cela, vous devez :
1.
2.
3.
4.

indiquer que le contenu du Table View sera dni dans le code ;


donner un nom au prototype des cellules ;
indiquer au contrle Table View combien de donnes il doit acher ;
relier l'objet Table View et l'objet maListe.

Pour indiquer que le contenu du Table View sera dni dans le code, cliquez sur
dans le volet de navigation (1), comme indiqu la

MainStoryboard.storyboard

285

CHAPITRE 16.

TP : UN NAVIGATEUR WEB TRS CIBL

Figure 16.4  Le contenu du Table

View

doit tre dni dans le code

gure 16.4. Cliquez sur le Table View dans le canevas (2), achez le volet des utilitaires en cliquant sur Show or hide the Utilities (3), achez l'inspecteur des attributs en cliquant sur Show the Attributes inspector (4) puis choisissez Dynamic
Properties dans le paramtre Content (5).
Pour donner un nom au prototype des cellules et ainsi viter l'achage d'un avertissement dans la barre d'outils de Xcode, cliquez sur la cellule ache sous Prototype
Cells dans le canevas (1) et renseignez la zone de texte Identifier (2), comme la
gure 16.5.
Enn, pour indiquer au contrle Table View combien de donnes il doit acher, et an
de relier les objets Tab View et maListe, dnissez les mthodes numberOfRowsInSection
et cellForRowAtIndexPath dans le chier MasterViewController.m :
1
2
3
4
5
6
7
8
9
10

- ( NSInteger ) tableView :( UITableView *) tableView


numberOfRowsInSection :( NSInteger ) section
{
return [ mesFavoris count ];
}
- ( UITableViewCell *) tableView :( UITableView *) tableView
cellForRowAtIndexPath :( NSIndexPath *) indexPath
{
static NSString * CellIdentifier = @" MyIdentifier " ;

286

UITableViewCell * cell = [ tableView

CORRECTION

Figure 16.5  Il faut donner un nom au prototype des cellules an d'viter l'achage
d'un avertissement
dequeueReusableCellWithIdentifier : CellIdentifier ];
if ( cell == nil ) {
cell = [[ UITableViewCell alloc ] initWithStyle :
UITableViewCellStyleDefault reuseIdentifier :
CellIdentifier ];
}

11
12
13
14
15
16
17
18
19

// Configuration des cellules


NSString * cellValue = [ mesFavoris objectAtIndex : indexPath . row
];
cell . textLabel . text = cellValue ;
return cell ;

Si vous cliquez sur Run, la fentre du simulateur iOS ache triomphalement vos sites
favoris.

Insertion du contrle Web View et liaison au code


Pour ceux qui auraient la mmoire courte, les contenus Web sont achs
dans des contrles Web View.

Cliquez sur

MainStoryboard.storyboard

dans le volet de navigation, cliquez sur


287

CHAPITRE 16.

TP : UN NAVIGATEUR WEB TRS CIBL

dans le canevas, supprimez le contrle Label dans lequel apparat le


texte  Detail view content goes here  et remplacez-le par un contrle Web View que
vous redimensionnerez pour lui donner tout l'espace disponible dans la vue.
Pour que le contrle Web View puisse communiquer avec le code, vous allez dnir
un outlet. Dans la barre d'outils de Xcode, au-dessus du libell Editor, cliquez sur
l'icne Show the Assistant editor. Contrle-glissez-dposez le contrle Web View
dans le chier d'en-ttes DetailViewController.h, juste au-dessus du @end nal. Au
relchement du bouton gauche de la souris, donnez le nom  pageWeb  l'outlet et
validez en cliquant sur Connect. Le code du chier d'en-ttes DetailViewController.h
doit maintenant ressembler ceci :

Detail view

1
2
3
4
5
6
7
8
9
10

# import < UIKit / UIKit .h >


@interface DetailViewController : UIViewController
@property ( strong , nonatomic ) id detailItem ;
@property ( strong , nonatomic ) IBOutlet UILabel *
detailDescriptionLabel ;
@property ( weak , nonatomic ) IBOutlet UIWebView * pageWeb ;
@end

Mise en relation des deux vues


Vous allez maintenant relier la vue Master la vue Detail. Comme d'habitude, cliquez
sur MainStoryboard.storyboard dans le volet de navigation. Comme le montre la
gure 16.6, cliquez sur l'lment qui reprsente une cellule dans la vue Master (1) puis
contrle-glissez-dposez cet lment sur la vue Detail (2). Au relchement du bouton
gauche de la souris, slectionnez Push dans le menu (3).
Pour pouvoir faire rfrence cette liaison dans le code, vous allez lui donner un
nom. Comme la gure 16.7, cliquez sur le symbole qui identie la liaison dans le
canevas (1), sur l'icne Hide or show the Utilities dans la barre d'outils (2), sur
Show the Attributes inspector dans le volet des utilitaires (3) puis donnez le nom
 detailSegue  la liaison (4).

Partage de donnes entre les deux vues


Lorsque l'utilisateur slectionne un lment dans le contrle Table View, la vue Detail
remplace la vue Master. Pour passer des informations de la vue Master la vue Detail,
vous allez utiliser la mthode prepareForSegue. Pour cela, vous devez passer par une
variable intermdiaire. Cliquez sur DetailViewController.h dans le volet de navigation et dnissez la proprit siteSelectionne comme suit :
1

288

@property ( strong , nonatomic ) id siteSelectionne ;

CORRECTION

Figure 16.6  Il faut relier la vue Master la vue Detail

Figure 16.7  Il faut donner un nom la liaison pour pouvoir y faire rfrence

289

CHAPITRE 16.

Le chier
vantes :
1
2
3
4
5
6
7
8
9
10

TP : UN NAVIGATEUR WEB TRS CIBL

DetailViewController.h

doit maintenant contenir les instructions sui-

# import < UIKit / UIKit .h >


@interface DetailViewController : UIViewController
@property ( strong , nonatomic ) id detailItem ;
@property ( strong , nonatomic ) id siteSelectionne ;
@property ( strong , nonatomic ) IBOutlet UILabel *
detailDescriptionLabel ;
@property ( weak , nonatomic ) IBOutlet UIWebView * pageWeb ;
@end

Cliquez sur DetailViewController.m dans le volet de navigation et ajoutez une instruction synthesize pour pouvoir accder la proprit siteSelectionne :
@synthesize siteSelectionne = _siteSelectionne ;

Ah, encore une petite chose : comme vous allez faire rfrence la vue Detail dans la
vue Master, vous devez galement ajouter une instruction #import au dbut du chier
MasterViewController.m. Cliquez sur MasterViewController.m dans le volet de navigation et insrez l'instruction suivante, juste aprs l'instruction #import existante :
1

# import " DetailViewController . h "

Vous pouvez maintenant insrer la mthode prepareForSegue. Si ce n'est pas dj


fait, cliquez sur MasterViewController.m dans le volet de navigation et insrez les
instructions suivantes dans le code (peu importe l'endroit) :
1
2
3
4
5
6
7
8

-( void ) prepareForSegue :( UIStoryboardSegue *) segue sender :( id )


sender {
if ([[ segue identifier ] isEqualToString : @ " detailSegue " ])
{
NSInteger selectedIndex = [[ self . tableView
indexPathForSelectedRow ] row ];
DetailViewController * dvc = [ segue
destinationViewController ];
dvc . siteSelectionne = [ NSString stringWithFormat : @ " % @ " , [
adressesWeb objectAtIndex : selectedIndex ]];
}
}

L'adresse du site slectionn est mmorise dans la variable d'instance siteSelectionne


de la vue Detail (dvc.siteSelectionne). L'adresse est obtenue partir du tableau
adressesWeb, et plus prcisment de la cellule dont l'index correspond celui de la cellule slectionne ([adressesWeb objectAtIndex:selectedIndex]). L'lment obtenu
est converti en un NSString avant d'tre mmoris dans la variable siteSelectionne
([NSString stringWithFormat:@"%@", ...) :
290

CORRECTION

dvc . siteSelectionne = [ NSString stringWithFormat : @ " % @ " , [


adressesWeb objectAtIndex : selectedIndex ]];

Vous devez enn rcuprer le site slectionn dans DetailViewController.m et acher la page correspondante. Cliquez sur DetailViewController.m dans le volet de
navigation et compltez la mthode viewDidLoad comme ceci :
1

[ _pageWeb loadRequest :[ NSURLRequest requestWithURL : [ NSURL


URLWithString : _siteSelectionne ]]];

Cette instruction demande l'achage du site d'adresse siteSelectionne dans le contrle

Web View.

Vous pouvez excuter l'application en cliquant sur Run. Quelle russite !


Les chiers de cette application se trouvent dans le dossier favoris. Vous pouvez copier
les codes de cette application grce au code web suivant.


Copier ce code
B
Code web : 234496


MasterViewController.h
1
2
3
4
5
6
7
8
9

# import < UIKit / UIKit .h >


@interface MasterViewController : UITableViewController
{
NSMutableArray * mesFavoris ;
NSMutableArray * adressesWeb ;
}
@end

MasterViewController.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# import " MasterViewController . h"


# import " DetailViewController . h"
@implementation MasterViewController
- ( void ) awakeFromNib
{
[ super awakeFromNib ];
}
- ( void ) didReceiveMemoryWarning
{
[ super didReceiveMemoryWarning ];
// Release any cached data , images , etc that aren 't in use .
}

291

CHAPITRE 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

# pragma mark - View lifecycle


- ( void ) viewDidLoad
{
[ super viewDidLoad ];
mesFavoris = [[ NSMutableArray alloc ] init ];
[ mesFavoris addObject : @ " Google " ];
[ mesFavoris addObject : @ " Le Site du Z ro " ];
[ mesFavoris addObject : @ " Mediaforma " ];
self . navigationItem . title = @ " Mes sites Web pr f r s " ;
adressesWeb = [[ NSMutableArray alloc ] init ];
[ adressesWeb addObject : @ " http :// www . google . fr " ];
[ adressesWeb addObject : @ " http :// www . siteduzero . com " ];
[ adressesWeb addObject : @ " http :// www . mediaforma . com " ];
}
- ( NSInteger ) tableView :( UITableView *) tableView
numberOfRowsInSection :( NSInteger ) section
{
return [ mesFavoris count ];
}
- ( UITableViewCell *) tableView :( UITableView *) tableView
cellForRowAtIndexPath :( NSIndexPath *) indexPath
{
static NSString * CellIdentifier = @" MyIdentifier " ;
UITableViewCell * cell = [ tableView
dequeueReusableCellWithIdentifier : CellIdentifier ];
if ( cell == nil ) {
cell = [[ UITableViewCell alloc ] initWithStyle :
UITableViewCellStyleDefault reuseIdentifier :
CellIdentifier ];
}

45
46
47
48
49
50
51
52
53
54
55

TP : UN NAVIGATEUR WEB TRS CIBL

56
57
58

292

// Configuration des cellules


NSString * cellValue = [ mesFavoris objectAtIndex : indexPath . row
];
cell . textLabel . text = cellValue ;
return cell ;

-( void ) prepareForSegue :( UIStoryboardSegue *) segue sender :( id )


sender {
if ([[ segue identifier ] isEqualToString : @ " detailSegue " ])
{
NSInteger selectedIndex = [[ self . tableView
indexPathForSelectedRow ] row ];

CORRECTION

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
88
89
90
91
92
93
94
95
96
97

DetailViewController * dvc = [ segue


destinationViewController ];
dvc . siteSelectionne = [ NSString stringWithFormat : @ " % @ " , [
adressesWeb objectAtIndex : selectedIndex ]];

- ( void ) viewDidUnload
{
[ 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

DetailViewController.h
1
2
3
4

# import < UIKit / UIKit .h >


@interface DetailViewController : UIViewController

293

CHAPITRE 16.

@property ( strong , nonatomic ) id detailItem ;


@property ( strong , nonatomic ) id siteSelectionne ;
@property ( strong , nonatomic ) IBOutlet UILabel *
detailDescriptionLabel ;
@property ( weak , nonatomic ) IBOutlet UIWebView * pageWeb ;

5
6
7
8
9
10

TP : UN NAVIGATEUR WEB TRS CIBL

@end

DetailViewController.m
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

# import " DetailViewController . h "


@interface DetailViewController ()
- ( void ) configureView ;
@end
@implementation DetailViewController
@synthesize
@synthesize
@synthesize
@synthesize

detailItem = _detailItem ;
detailDescriptionLabel = _detailDescriptionLabel ;
pageWeb = _pageWeb ;
siteSelectionne = _siteSelectionne ;

# pragma mark - Managing the detail item


- ( void ) setDetailItem :( id ) newDetailItem
{
if ( _detailItem != newDetailItem ) {
_detailItem = newDetailItem ;

// Update the view .


[ self configureView ];

- ( void ) configureView
{
// Update the user interface for the detail item .

if ( self . detailItem ) {
self . detailDescriptionLabel . text = [ self . detailItem
description ];
}

- ( void ) didReceiveMemoryWarning
{
[ super didReceiveMemoryWarning ];
// Release any cached data , images , etc that aren 't in use .
}

294

CORRECTION

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

# pragma mark - View lifecycle


- ( void ) viewDidLoad
{
[ super viewDidLoad ];
[ self configureView ];
[ _pageWeb loadRequest :[ NSURLRequest requestWithURL : [ NSURL
URLWithString : _siteSelectionne ]]];
}
- ( void ) viewDidUnload
{
[ self setPageWeb : 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

295

CHAPITRE 16.

TP : UN NAVIGATEUR WEB TRS CIBL

Aller plus loin


Vous voulez aller plus loin ? Pas de problme, mais attention, cela sort du cadre de ce
TP. Vous pourriez :
1. autoriser l'ajout de sites via le clavier ;
2. permettre l'utilisateur de mmoriser le site en cours de visualisation dans les
favoris ;
3. dnir des favoris sur deux niveaux, en utilisant deux Table View ;
4. permettre une gestion avance des favoris en autorisant (par exemple) les dplacements, suppressions et modications de noms.

296

Quatrime partie
Plus loin avec iOS 5

297

Chapitre

17

Golocalisation
Dicult :

ans ce chapitre, vous allez apprendre utiliser quelques-unes des mthodes du framework CoreLocation pour  golocaliser  (c'est--dire obtenir la position) d'un
iPhone, iPad ou iPod Touch. Vous apprendrez galement calculer la vitesse de dplacement du device et transformer un couple longitude/latitude en une adresse physique,
bien plus parlante pour nous, pauvres humains.

299

CHAPITRE 17.

GOLOCALISATION

Longitude et latitude
Pour donner la position d'un point sur la Terre, on utilise souvent sa latitude et sa
longitude.
 Un parallle est un cercle imaginaire parallle l'quateur.
 La latitude est la distance mesure en degrs qui spare un parallle de l'quateur.
 Un mridien est un demi-cercle imaginaire qui relie les deux ples.
 Les mridiens de rfrence utiliss sont celui de Greenwich (longitude 0) et celui
de l'observatoire de Paris (220'14,025 l'est du mridien de Greenwich).
 La longitude est la distance mesure en degrs qui spare un mridien du mridien
de rfrence.
Si vous avez un peu de mal vous reprsenter tout a, je vous conseille de regarder la
gure 17.1.

Figure 17.1  La latitude et la longitude permettent de dterminer avec prcision un

point sur la Terre

Ces quelques notions de base tant poses, nous allons dnir une application qui
renvoie la longitude et la latitude d'un device (iPhone, iPod Touch ou iPad 2). Les
informations de golocalisation utilises pourront provenir de rseaux cellulaires, WiFi et/ou GPS. Attaquons sans plus tarder.
Commencez par dnir un nouveau projet bas sur le modle Single View Application
et donnez-lui le nom  ouSuisJe . Toutes les mthodes relatives la golocalisation se
trouvant dans le framework CoreLocation, la premire tape va consister ajouter ce
framework l'application.
300

LONGITUDE ET LATITUDE

Comme la gure 17.2, cliquez sur la premire icne ache dans le volet de navigation
(1) et slectionnez l'onglet Build Phases dans la zone d'dition (2). Dveloppez l'entre
Link Binary With Libraries (3). Cliquez sur l'icne + (4), slectionnez le framework
CoreLocation.framework et cliquez sur Add (5).

Figure 17.2  Ajoutez le framework CoreLocation l'application

Nous allons acher les coordonnes 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 gure 17.3. Agrandissez ce contrle et slectionnez
Show the Attributes inspector dans le volet des utilitaires (3). Aectez la valeur
 Recherche de la position en cours  la proprit Text (4) et la valeur  10  la
proprit Lines (5).
Pourquoi aecter la valeur 10 la proprit Lines du Label ?

Ce Label va tre utilis pour acher des informations relatives la position du device.
La mthode utilise pour obtenir ces informations est trs  verbeuse . C'est la raison
pour laquelle autant de lignes sont attribues au Label. Si vous limitez la taille du
Label deux ou trois lignes seulement, l'information ache a toutes les chances
d'tre tronque !
Cliquez sur l'icne Show the Assistant editor dans la barre d'outils. Contrle-glissezdposez le Label juste au-dessus du @end nal et dnissez l'outlet maPosition pour
le Label.
301

CHAPITRE 17.

GOLOCALISATION

Figure 17.3  Nous allons acher les coordonnes du device dans un Label

Cliquez sur ViewController.h dans le volet de navigation et ajoutez une instruction


#import au chier d'en-ttes pour faire rfrence au framework CoreLocation :
1
2
3

# import < UIKit / UIKit .h >


# import < CoreLocation / CoreLocation .h >
...

Comme l'indique la documentation Apple, les informations de golocalisation sont obtenues travers la classe CLLocationManager. Cette dernire est accessible travers
le protocole CLLocationManagerDelegate. Vous allez donc devoir implmenter ce protocole dans le code de l'application.
Cliquez sur ViewController.h dans le volet de navigation et ajoutez le protocole dans
la dclaration de l'interface :
@interface ViewController : UIViewController <
CLLocationManagerDelegate >

Dnissez ensuite la variable d'instance locationManager de classe CLLocationLManager :


1
2
3
4

@interface ViewController : UIViewController <


CLLocationManagerDelegate >
{
CLLocationManager * locationManager ;
}

302

LONGITUDE ET LATITUDE

Comme nous le verrons un peu plus loin, c'est par l'intermdiaire de cette variable d'instance que le processus de golocalisation sera lanc. Le chier d'en-ttes doit maintenant
avoir l'allure suivante :
1
2
3
4
5
6
7
8
9
10

# 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 dnition du code. Cliquez sur ViewController.m dans le


volet de navigation et compltez la mthode viewDidLoad comme suit :
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 dni et initialis :
1

locationManager = [[ CLLocationManager alloc ] init ];

Pour avoir de plus amples informations sur la classe CLLocationManager,


consultez la documentation Apple. Le code web suivant vous permet d'y
accder directement.

Aller la doc
Code web : 570655


L'instruction de la ligne 5 teste si le service de golocalisation est disponible et activ :

if ([ CLLocationManager locationServicesEnabled ]) {

Cette instruction est ncessaire : en eet, si le mode  Avion  est activ ou si les
priphriques de golocalisation ne sont pas en mesure de fournir des informations, il
est inutile de chercher en obtenir.
303

CHAPITRE 17.

GOLOCALISATION

L'instruction de la ligne 7 aecte la valeur self la proprit delegate de l'objet locationManager an d'indiquer que les vnements relatifs la golocalisation
doivent tre traits dans ViewController.m :
locationManager . delegate = self ;

L'instruction de la ligne 8 dnit la prcision dsire :


locationManager . desiredAccuracy = kCLLocationAccuracyBest ;

La constante utilise (kCLLocationAccuracyBest) demande la meilleure prcision possible. Si vous le souhaitez, vous pouvez utiliser une autre prcision. Par exemple,
kCLLocationAccuracyHundredMeters pour obtenir une prcision de cent mtres. Consultez la section intitule  Core Location Constants Reference  dans la documentation
Apple pour prendre connaissance de toutes les constantes disponibles.


Aller

la
doc
B
Code web : 380969


Mais pourquoi ne pas utiliser systmatiquement la meilleure prcision possible ?

Cela semble en eet une bonne solution. . . si la batterie du device est entirement
charge. Dans le cas contraire, la golocalisation fonctionnera certes d'une faon trs
prcise, mais pour une dure assez courte. En eet, prcision 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 dnit la distance de dplacement minimale du device avant qu'une mise
jour de la position ne soit eectue. Dans cet exemple, il faudra que le device se dplace
de 100 mtres pour qu'une notication de changement de position soit faite :
locationManager . distanceFilter = 100 . 0f ;

La ligne 10 excute la mthode startUpdatingLocation. En d'autres termes, elle demande au device de mettre jour de faon rgulire ses coordonnes gographiques, en
accord avec les paramtres dnis prcdemment (prcision et dplacement minimum
pour mise jour) :
1

[ locationManager startUpdatingLocation ];

L'implmentation du protocole CLLocationManagerDelegate et la dnition de l'objet locationManager ne sont pas susantes. Vous devez galement faire appel aux
mthodes :
 locationManager:didUpdateToLocation:fromLocation: pour savoir si une nouvelle position est disponible ;
 locationManager:didFailWithError: qui indique, le cas chant, qu'aucune position ne peut tre dtermine pour le device.
304

LONGITUDE ET LATITUDE

Ces deux mthodes sont abondamment documentes dans la documentation Apple qui
donne, entre autres choses, les en-ttes de ces deux fonctions. Ajoutez ces en-ttes dans
le chier ViewController.m et compltez-les comme suit :
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 gnre, la mthode
locationManager:didUpdateToLocation:fromLocation: est excute. Le nouvel emplacement ([newLocation description]) est alors ach dans le Label :
1

maPosition . text = [ newLocation description ];

Lorsque le systme de golocalisation du device n'est pas en mesure de donner des coordonnes gographiques, la mthode locationManager:didFailWithError: est excute. Le message d'erreur ([error description];) est alors ach dans le Label
(maPosition.text) :
1

maPosition . text = [ error description ];

Allez-y, lancez l'application, vous l'avez bien mrit !


Je suppose que vous testez cette application dans le simulateur iOS. Dans ce cas, une
bote de dialogue devrait s'acher, comme la gure 17.4.
Validez en cliquant sur OK. Regardez la gure 17.5, le rsultat est plutt fantaisiste.
Pour avoir des rsultats cohrents, une seule solution : testez l'application sur un device !
Le code de l'application se trouve dans le dossier ouSuisJe.


Copier ce code
B
Code web : 976860


ViewController.h
1
2
3
4
5
6

# import < UIKit / UIKit .h >


# import < CoreLocation / CoreLocation .h >
@interface ViewController : UIViewController <
CLLocationManagerDelegate >
{
CLLocationManager * locationManager ;

305

CHAPITRE 17.

GOLOCALISATION

Figure 17.4  Une bote de dialogue s'ache dans le simulateur

Figure 17.5  Le rsultat de la golocalisation est plutt fantaisiste

306

LONGITUDE ET LATITUDE

7
8
9
10

}
@property ( weak , nonatomic ) IBOutlet UILabel * maPosition ;
@end

ViewController.m
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

# 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 .

307

CHAPITRE 17.

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

GOLOCALISATION

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

Vitesse
En utilisant le mme principe que dans l'application prcdente, et en y ajoutant la
proprit speed de l'objet locationManager, il est possible d'obtenir la vitesse instantane du device.
Dnissez un nouveau projet bas sur le modle Single View Application et donnezlui le nom  vitesse . Ajoutez le framework CoreLocation dans ce projet et implmentez le protocole CLLocationManagerDelegate comme vous l'avez fait dans la section
prcdente. Insrez un Label dans la vue du projet et attachez-lui l'outlet laVitesse.
Copiez-collez les en-ttes du chier ViewController.h du projet ouSuisJe dans le
chier ViewController.h du projet vitesse. Voici ce que vous devriez obtenir :
1
2
3

# import < UIKit / UIKit .h >


# import < CoreLocation / CoreLocation .h >

308

VITESSE

4
5
6
7
8
9
10

@interface ViewController : UIViewController <


CLLocationManagerDelegate >
{
CLLocationManager * locationManager ;
}
@property ( weak , nonatomic ) IBOutlet UILabel * laVitesse ;
@end

Copiez-collez la mthode viewDidLoad du chier ViewController.m du projet ouSuisJe


dans le chier ViewController.m du projet vitesse.
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 = 10 . 0f ;
[ locationManager startUpdatingLocation ];
}
}

Copiez-collez la mthode locationManager:didUpdateToLocation:fromLocation: du


chier ViewController.m du projet ouSuisJe dans le chier ViewController.m du
projet vitesse, puis modiez-la comme suit :
1
2
3
4
5
6
7
8
9
10

- ( void ) locationManager :( CLLocationManager *) manager


didUpdateToLocation :( CLLocation *) newLocation
fromLocation :( CLLocation *) oldLocation
{
if ( newLocation . speed > 0 . 0 )
{
NSString * vitesseString = [ NSString stringWithFormat : @ "
Votre vitesse instantan e : % 0 . 1f m / s " , newLocation . speed
];
laVitesse . text = vitesseString ;
}
}

Rappelons que cette mthode est excute chaque fois que le device change de position,
en accord avec les paramtres de prcision et de  distance de boug  dnis dans
l'objet locationManager.
Examinons les nouvelles instructions de cette mthode.
La condition ligne 5 teste si la vitesse instantane est suprieure zro, c'est--dire si
le device est en mouvement :
1

if ( newLocation . speed > 0 . 0 )

309

CHAPITRE 17.

GOLOCALISATION

Dans ce cas, la vitesse instantane doit tre ache dans le Label laVitesse. tant
donn que la proprit speed est un nombre ottant et que la proprit text du Label
est de type NSString, il est ncessaire d'eectuer une conversion de type. C'est le but
de la premire instruction qui suit le if :
NSString * vitesseString = [ NSString stringWithFormat : @ " Votre
vitesse instantan e : % 0 . 1f m / s " , newLocation . speed ];

Le NSString vitesseString est dni (NSString* vitesseString), puis il est initialis avec un String ([NSString stringWithFormat:@"..."]) obtenu en concatnant
une chane de caractres ( Votre vitesse instantane : ), la vitesse instantane ottante (%0.1f) et une autre chane de caractres ( m/s ).
Il sut maintenant d'acher cette chane dans le label laVitesse en agissant sur sa
proprit text :
laVitesse . text = vitesseString ;

Modiez galement la proprit distanceFilter de l'objet locationManager et aectezlui la valeur 10.0f.


Enn, copiez-collez la mthode locationManager:didFailWithError: prsente dans
le chier ViewController.m du projet ouSuisJe dans le chier ViewController.m du
projet vitesse, puis modiez-la comme suit :
1
2
3
4
5

- ( void ) locationManager :( CLLocationManager *) manager


didFailWithError :( NSError *) error
{
laVitesse . text = [ error description ];
}

Il ne vous reste plus qu' uploader ce projet sur votre device et aller le tester sur le
terrain.
Ce projet se trouve dans le dossier vitesse.
ViewController.h
1
2
3
4
5
6
7
8
9
10

# import < UIKit / UIKit .h >


# import < CoreLocation / CoreLocation .h >
@interface ViewController : UIViewController <
CLLocationManagerDelegate >
{
CLLocationManager * locationManager ;
}
@property ( weak , nonatomic ) IBOutlet UILabel * laVitesse ;
@end

ViewController.m

310

VITESSE

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

# import " ViewController . h "


@implementation ViewController
@synthesize laVitesse ;
- ( 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 = 10 . 0f ;
[ locationManager startUpdatingLocation ];
}
}
- ( void ) locationManager :( CLLocationManager *) manager
didUpdateToLocation :( CLLocation *) newLocation
fromLocation :( CLLocation *) oldLocation
{
if ( newLocation . speed > 0 . 0 )
{
NSString * vitesseString = [ NSString stringWithFormat : @ "
Votre vitesse instantan e : % 0 . 1f m / s " , newLocation . speed
];
laVitesse . text = vitesseString ;
}
}
- ( void ) locationManager :( CLLocationManager *) manager
didFailWithError :( NSError *) error
{
laVitesse . text = [ error description ];
}
- ( void ) viewDidUnload
{
[ self setLaVitesse : nil ];
[ super viewDidUnload ];
// Release any retained subviews of the main view .
// e . g . self . myOutlet = nil ;

311

CHAPITRE 17.

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

GOLOCALISATION

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

Copier ce code
B
Code web : 893789

Golocalisation inverse
Le processus de  golocalisation inverse  consiste trouver l'adresse qui correspond
un couple longitude/latitude. Le framework MapKit donne accs une classe de
golocalisation inverse lie Google Maps.
Le principe en est dtaill ci-aprs.
1. Implmentation du protocole CLLocationManagerDelegate, dnition de l'objet
locationManager et utilisation de la mthode
1

- locationManager : didUpdateToLocation : fromLocation :

pour obtenir la position du device. Cette technique a t dcrite dans la premire


section de ce chapitre.
312

GOLOCALISATION INVERSE

2. Implmentation du protocole MKReverseGeocoderDelegate et utilisation des coordonnes locales obtenues dans l'tape 1 pour trouver l'adresse correspondante
via la mthode
1

- reverseGeocoder : geocoder didFindPlacemark : placemark

3. Achage de l'adresse dans un contrle UITextView dpos dans la vue de l'application.


Commencez par dnir une nouvelle application base sur le modle Single View
Application et donnez-lui le nom  geolocalisationInverse . Cette application va utiliser les frameworks CoreLocation (pour trouver la longitude et la latitude du device)
et MapKit (pour eectuer la golocalisation inverse). La premire tape va donc consister ajouter ces frameworks l'application.
1. Cliquez sur la premire icne ache dans le volet de navigation.
2. Slectionnez l'onglet Build Phases dans la zone d'dition.
3. Dveloppez l'entre Link Binary With Libraries.
4. Cliquez sur l'icne +, slectionnez le framework CoreLocation.framework et cliquez sur Add.
5. Cliquez sur l'icne +, slectionnez le framework MapKit.framework et cliquez sur
Add.
Cliquez sur MainStoryboard.storyboard dans le volet de navigation et ajoutez un
contrle UITextView la vue de l'application. Cliquez sur l'icne Show the Assistant
editor dans la barre d'outils et contrle-glissez-dposez le contrle de la zone d'dition
dans le chier d'en-ttes, juste au-dessus du @end nal. Dnissez l'outlet ladresse
pour ce contrle.
Vous allez maintenant modier le chier d'en-ttes. Ajoutez deux instructions #import
pour accder aux framework MapKit et CoreLocation :
1
2
3
4

# import < UIKit / UIKit .h >


# import < MapKit / MapKit .h >
# import < CoreLocation / CoreLocation .h >
...

Ajoutez les protocoles MKReverseGeocoderDelegate et CLLocationManagerDelegate


dans la dnition de l'interface et dnissez la variable d'instance locationManager
de type CLLocationManager :
1
2
3
4

@interface geolocalisationInverseViewController :
UIViewController < MKReverseGeocoderDelegate ,
CLLocationManagerDelegate >
{
CLLocationManager * locationManager ;
}

Le chier ViewController.h doit maintenant avoir l'allure suivante :


313

CHAPITRE 17.

1
2
3
4
5
6
7
8
9
10
11
12

GOLOCALISATION

# import < UIKit / UIKit .h >


# import < MapKit / MapKit .h >
# import < CoreLocation / CoreLocation .h >
@interface ViewController : UIViewController <
MKReverseGeocoderDelegate , CLLocationManagerDelegate >
{
CLLocationManager * locationManager ;
}
@property ( weak , nonatomic ) IBOutlet UITextView * ladresse ;
@end

Vous avez peut-tre remarqu le panneau  Attention  de couleur jaune afch dans la marge gauche du code (gure 17.6). Si vous cliquez dessus, un
message vous indique que MKReverseGeocoderDelegate est  deprecated 
(c'est--dire obsolte en bon franais). Que cela ne vous eraie pas : ce delegate est toujours utilisable et entirement fonctionnel. Il se peut cependant
qu'il soit remplac dans la version 6 d'iOS. Je vous conseille donc d'ignorer
cet avertissement.

Figure 17.6  Un panneau  Attention  de couleur jaune est ach dans la marge

gauche du code

Vous allez maintenant modier le code de l'application. Cliquez sur ViewController.m.


Votre premire action va consister lancer une golocalisation en agissant sur la mthode viewDidLoad :
1
2
3
4
5
6
7
8
9
10
11

- ( void ) viewDidLoad
{
locationManager = [[ CLLocationManager alloc ] init ];
if ([ CLLocationManager locationServicesEnabled ]) {
locationManager . delegate = self ;
locationManager . desiredAccuracy = kCLLocationAccuracyBest ;
locationManager . distanceFilter = 10 . 0f ;
[ locationManager startUpdatingLocation ];
}
[ super viewDidLoad ];
}

Ici encore, plusieurs signes  Attention  apparaissent dans la marge gauche


du code. Ignorez-les : les mthodes et objets concerns sont totalement fonctionnels avec iOS 5.

314

GOLOCALISATION INVERSE

Jusqu'ici, rien de nouveau. Si ncessaire, reportez-vous la premire section de ce chapitre pour avoir des explications dtailles sur ce code. Si une erreur se produit pendant
la tentative de golocalisation, la mthode locationManager:didFailWithError est
excute. Le message d'erreur correspondant ([error description]) est alors ach
dans le TextView (ladresse.text) :
1
2
3
4
5

- ( void ) locationManager :( CLLocationManager *) manager


didFailWithError :( NSError *) error
{
ladresse . text = [ error description ];
}

Si la position du device est identie, la mthode


1

- locationManager : didUpdateToLocation : fromLocation :

est excute. Dnissez cette mthode et compltez-la comme suit :


1
2
3
4
5
6
7
8

- ( void ) locationManager :( CLLocationManager *) manager


didUpdateToLocation :( CLLocation *) newLocation
fromLocation :( CLLocation *) oldLocation
{
MKReverseGeocoder * geocoder = [[ MKReverseGeocoder alloc ]
initWithCoordinate : newLocation . coordinate ];
geocoder . delegate = self ;
[ geocoder start ];
}

Cette mthode dnit l'objet geocoder de type MKReverseGeocoder et l'initialise avec


les coordonnes gographiques retournes la mthode didUpdateTo :
1

MKReverseGeocoder * geocoder = [[ MKReverseGeocoder alloc ]


initWithCoordinate : newLocation . coordinate ];

L'instruction suivante indique que la gestion des vnements (delegate) lis l'objet
(c'est--dire la golocalisation inverse) se fera dans la classe courante :

geocoder
1

geocoder . delegate = self ;

Enn, la dernire instruction lance le processus de golocalisation inverse :


1

[ geocoder start ];

Si une erreur se produit pendant le processus de golocalisation inverse, la mthode


reverseGeocoder: didFailWithError est excute. Le message d'erreur correspondant ([error description]) est alors ach dans le TextView (ladresse.text) :
1
2
3
4

- ( void ) reverseGeocoder : ( MKReverseGeocoder *) geocoder


didFailWithError :( NSError *) error
{
ladresse . text = [ error description ];
}

315

CHAPITRE 17.

GOLOCALISATION

Si une adresse a pu tre associe au couple longitude/latitude du device, la mthode


reverseGeocoder: didFindPlacemark est excute. Compltez cette mthode comme
suit :
1
2
3
4

- ( void ) reverseGeocoder :( MKReverseGeocoder *) geocoder


didFindPlacemark :( MKPlacemark *) placemark
{
ladresse . text = [ placemark . addressDictionary description ];
}

L'unique instruction de cette mthode ache l'adresse complte dans le contrle TextView.
Il ne vous reste plus qu' uploader cette application sur votre device et la tester en
vous baladant prs de chez vous. Vous devriez obtenir quelque chose comme la gure
17.7.

Figure 17.7  Rsultat de la golocalisation inverse

Le code de l'application se trouve dans le dossier geolocalisationInverse.




Copier
ce
code
B
Code web : 292862


ViewController.h
1
2

# import < UIKit / UIKit .h >


# import < MapKit / MapKit .h >

316

GOLOCALISATION INVERSE

3
4
5
6
7
8
9
10
11
12

# import < CoreLocation / CoreLocation .h >


@interface ViewController : UIViewController <
MKReverseGeocoderDelegate , CLLocationManagerDelegate >
{
CLLocationManager * locationManager ;
}
@property ( weak , nonatomic ) IBOutlet UITextView * ladresse ;
@end

ViewController.m
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

# import " ViewController . h "


@implementation ViewController
@synthesize ladresse ;
- ( 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 = 10 . 0f ;
[ locationManager startUpdatingLocation ];
}
}
- ( void ) locationManager :( CLLocationManager *) manager
didFailWithError :( NSError *) error
{
ladresse . text = [ error description ];
}
- ( void ) locationManager :( CLLocationManager *) manager
didUpdateToLocation :( CLLocation *) newLocation
fromLocation :( CLLocation *) oldLocation
{
MKReverseGeocoder * geocoder = [[ MKReverseGeocoder alloc ]

317

CHAPITRE 17.

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

GOLOCALISATION

initWithCoordinate : newLocation . coordinate ];


geocoder . delegate = self ;
[ geocoder start ];

- ( void ) reverseGeocoder :( MKReverseGeocoder *) geocoder


didFindPlacemark :( MKPlacemark *) placemark
{
ladresse . text = [ placemark . addressDictionary description ];
}
- ( void ) viewDidUnload
{
[ self setLadresse : 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

318

GOLOCALISATION INVERSE

En rsum
 Le framework CoreLocation permet de golocaliser un device, mais aussi de calculer
la vitesse de dplacement du device et de transformer un couple longitude/latitude
en une adresse physique.
 Pour golocaliser un device, vriez que le service de golocalisation est disponible
et activ, paramtrez la prcision et mettez jour les donnes de golocalisation.
 Pour calculer la vitesse instantane d'un device, utilisez le principe de la golocalisation et ajoutez-y la proprit speed de l'objet locationManager.
 Le processus de  golocalisation inverse  consiste trouver l'adresse qui correspond
un couple longitude/latitude. Le framework MapKit donne accs une classe de
golocalisation inverse lie Google Maps. Pour l'utiliser, vous dnirez un objet
de classe MKReverseGeocoder et vous lui appliquerez la mthode start.

319

CHAPITRE 17.

320

GOLOCALISATION

Chapitre

18

Multimdia : le son
Dicult :

es devices Apple sont en mesure de jouer et d'enregistrer des sons. Vous utilisez certainement l'application iPod pour couter vos albums prfrs et l'application Dictaphone
pour prendre des notes vocales. Que diriez-vous d'accder ces possibilits dans vos
propres applications ? C'est ce que vous allez dcouvrir dans ce chapitre. Vous devez penser
que le code utiliser est compliqu et que vous n'avez pas (encore) le niveau ncessaire !
Je vous rappelle que vous tes maintenant dans la quatrime partie de ce tutoriel et que vous
avez appris normment de choses dans les trois parties prcdentes. Dans ce chapitre, vous
allez relever un nouveau d, et je vous assure que vous vous en sortirez honorablement !
Alors commenons sans plus attendre. . .

321

CHAPITRE 18.

MULTIMDIA : LE SON

Jouer des lments audio


Plusieurs techniques permettent de jouer des sons sur un device. La plus simple consiste
passer par les  System Sound Services  du framework AudioToolbox. Une technique,
plus complexe, consiste utiliser un AVAudioPlayer.
Je vais vous montrer comment utiliser ces deux techniques. vous de choisir celle qui
est le mieux adapte aux applications que vous voulez raliser.

La technique  System Sound Services 


Cette technique est particulirement bien adapte aux sons utiliss dans l'interface
utilisateur d'une application : quand vous appuyez sur un bouton ou quand vous vous
dplacez dans un contrle par exemple.
Il y a cependant quelques restrictions.
1. Les sons doivent avoir une dure maximale de 30 secondes.
2. Seuls quelques codecs audio sont supports :
 AMR (Adaptive Multi-Rate) ;
 iLBC (internet Low Bitrate Codec) ;
 IMA/ADPCM (IMA-4) ;
 Linear PCM ;
 Law and aLaw.
Codec ? Qu'est-ce encore que cela ?

Codec est l'abrviation de  codeur/dcodeur . Les chiers audio sont gnralement


compresss pour rduire leur taille. Le format de compression (le codec) utilis dpend
de l'application dans laquelle le chier audio est cr. Pour qu'il puisse tre jou sur
une machine donne (un Mac, un PC, un iPhone, etc.), il faut que ce dernier dispose
du dcodeur correspondant. Les iPhone/iPod Touch/iPad disposent des codecs cits
plus haut.
Si un chier audio utilise un codec non reconnu, il ne sera pas jou sur le device. Pour
viter ce dsagrment, je vous conseille de convertir vos sons au format CAF en utilisant
le programme afconvert sur votre Mac.
Cliquez sur l'icne Applications dans le Dock, ouvrez le dossier Utilitaires puis
cliquez sur l'icne Terminal. Dplacez-vous dans le dossier qui contient le chier
convertir. Supposons que vous vouliez convertir le chier 22-new.aif en 22-new.caf ;
vous taperez quelque chose comme ceci :
afconvert -f caff -d LEI16@44100 22 - new . aif 22 - new . caf

322

JOUER DES LMENTS AUDIO

a me semble plutt indigeste comme commande. Pourrais-je avoir quelques


explications ?

Vous avez raison : la commande afconvert n'est pas trs  sexy . Mais quelle ecacit !
Elle permet de convertir peu prs tous les formats de chiers audio en une seule ligne.
Pour avoir toutes les informations ncessaires l'utilisation de cette commande, tapez
afconvert -h dans la fentre Terminal.
titre d'information, sachez que le paramtre LEI16@44100 demande une conversion
sur 16 bits avec un chantillonnage en 44100 Hz. Plus ces deux valeurs (16 et 44100)
sont leves, meilleur est le son obtenu. Mais aussi, plus grande est la taille du chier.
Faites quelques essais en utilisant une conversion sur 8, 16 et 24 bits en 11025, 22050 et
44100 Hz. Ce qui donne des paramtres compris entre LEI8@11025 et LEI24@44100.
vous de juger quel est le meilleur compromis entre la qualit sonore et la taille du
chier obtenu.
Voyons par la pratique comment utiliser les  System Sound Services  du framework
AudioToolbox. Nous allons travailler sur un chier audio nomm Applaudissements.caf.


Tlcharger
B applaudissements.caf

Code


web : 973650

Crez une nouvelle application base sur le modle Single View Application et
donnez-lui le nom  ecouteAudio .
Toutes les mthodes relatives aux  System Sound Services  se trouvent dans le framework AudioToolbox. La premire tape va donc consister ajouter ce framework
l'application. Pour cela, suivez les instructions visibles la gure 18.1.
1.
2.
3.
4.
5.
6.

Cliquez sur la premire icne ache dans le volet de navigation.


Slectionnez l'onglet Build Phases dans la zone d'dition.
Dveloppez l'entre Link Binary With Libraries.
Cliquez sur l'icne +.
Slectionnez AudioToolbox.framework dans la bote de dialogue.
Cliquez sur Add pour ajouter le framework au projet.

Pour jouer un son, vous allez placer le chier audio correspondant dans les ressources
de l'application. Cliquez du bouton droit sur la premire icne du volet de navigation
et slectionnez New Group dans le menu contextuel. Donnez le nom  Resources  ce
nouveau dossier, puis glissez-dposez le chier Applaudissements.caf du Finder dans
ce dossier.
Lorsque vous dposez le chier audio dans le dossier Resources, une
bote de dialogue est ache. Veillez cocher la case Copy items into
destination group's folder (if needed) pour que le chier soit copi
(et pas seulement rfrenc) dans les ressources.

323

CHAPITRE 18.

MULTIMDIA : LE SON

Figure 18.1  Ajoutez le framework AudioToolbox

En consultant la documentation Apple sur le terme  System Sound Services Reference , vous pouvez voir qu'il vous faudra utiliser les deux mthodes suivantes :
1. AudioServicesCreateSystemSoundID
2. AudioServicesPlaySystemSound
Ces mthodes proviennent du framework AudioToolbox/AudioServices.h et sont dclares dans le chier d'en-ttes AudioServices.h.
La prochaine tape va donc consister faire rfrence au framework dans le chier
d'en-ttes de l'application. Cliquez sur ViewController.h dans le volet de navigation
et ajoutez l'instruction #import suivante :
1

# import < AudioToolbox / AudioServices .h >

Le chier d'en-ttes doit maintenant ressembler ceci :


1
2
3
4
5
6

# import < UIKit / UIKit .h >


# import < AudioToolbox / AudioServices .h >
@interface ViewController : UIViewController
@end

Cliquez sur ViewController.m


viewDidLoad comme suit :
1
2

- ( void ) viewDidLoad
{

324

dans le volet de navigation et compltez la mthode

JOUER DES LMENTS AUDIO

3
4
5
6
7

[ super viewDidLoad ];
SystemSoundID bravo ;
AudioServicesCreateSystemSoundID ( CFBundleCopyResourceURL (
CFBundleGetMainBundle () , CFSTR ( " Applaudissements " ) , CFSTR (
" caf " ) , NULL ) , & bravo ) ;
AudioServicesPlaySystemSound ( bravo ) ;

Examinons les instructions contenues dans cette mthode. La ligne 4 dnit l'objet
bravo de type SystemSoundID. C'est dans cet objet que sera stock le son jouer.
La ligne 5 appelle la mthode AudioServicesCreateSystemSoundID. Ne soyez pas
erays par l'apparente complexit de cette mthode. Cette criture un peu lourde
vient du chanage (entendez par l, de l'excution conscutive) de plusieurs mthodes
dans une seule instruction. Procdons par tapes, et vous verrez que cette instruction
est tout fait comprhensible.
La mthode AudioServicesCreateSystemSoundID admet deux arguments : l'adresse
URL du chier audio jouer et l'adresse d'un objet SystemSoundID qui sera associe
au son. Voici quoi ressemble cette mthode :
1

AudioServicesCreateSystemSoundID ( URL - fichier - audio , adresse SystemSoundID ) ;

Bien que les applications iOS soient composes de plusieurs chiers, elles apparaissent sous la forme d'un chier unique appel  bundle . Ce chier renferme toute l'arborescence de l'application. Ainsi par exemple, les ressources
font partie du bundle de l'application.

Pour obtenir l'adresse URL d'un lment situ dans les ressources de l'application,
nous utilisons la mthode CFBundleCopyResourceURL. Cette mthode admet quatre
arguments : le nom du bundle examiner, le nom de la ressource, l'extension de la
ressource et le dossier dans lequel elle est stocke. Voici quoi ressemble cette mthode :
1

CFBundleCopyResourceURL ( nom - bundle , nom - ressource , extension ressource , dossier - ressource ) ;

Mais d'o viennent toutes ces informations ?

De la documentation Apple tout simplement ! Dans la page  System Sound Services


Reference , examinez la section AudioServicesCreateSystemSoundID et vous trouverez toutes les informations ncessaires.
Le bundle de l'application est obtenu avec la mthode CFBundleGetMainBundle. Viennent
ensuite le nom du chier (CFSTR("Applaudissements")), son extension (CFSTR("caf"))
et enn le dossier du chier (NULL).
325

CHAPITRE 18.

MULTIMDIA : LE SON

Pourquoi ne pas avoir utilis les chanes Applaudissements et caf dans le


deuxime et le troisime argument ? Et pourquoi le dernier argument est gal
NULL ?

Une fois encore, je vous renvoie la documentation Apple. Vous y apprendrez que le
deuxime et le troisime argument doivent tre des chanes constantes et non de simples
chanes. De plus, pour transformer une chane en une chane constante, il faut utiliser
la fonction CFSTR().
Quant au quatrime paramtre qui, rappelons-le, est cens dnir le dossier dans lequel
se trouve la ressource, la valeur NULL facilite l'criture. En eet, elle indique que c'est
au device de trouver dans quel dossier la ressource a t stocke. Tant que vous n'avez
pas plusieurs centaines de ressources, cette technique est tout fait possible. Alors,
pourquoi s'en passer ?
La mthode CFBundleCopyResourceURL a donc retourn l'adresse URL de la ressource.
Je vous rappelle que la mthode AudioServicesCreateSystemSoundID demande deux
paramtres : l'adresse URL du chier jouer et l'adresse d'un objet SystemSoundID.
Cette dernire est obtenue avec &bravo.
Nous arrivons donc l'instruction suivante :
AudioServicesCreateSystemSoundID ( CFBundleCopyResourceURL (
CFBundleGetMainBundle () , CFSTR ( " Applaudissements " ) , CFSTR ( "
caf " ) , NULL ) , & bravo ) ;

Je vous rassure tout de suite : le plus gros du travail a t fait. Maintenant, il suft d'appeler la mthode AudioServicesPlaySystemSound en lui transmettant l'objet
SystemSoundID pour dclencher la lecture du son :
AudioServicesPlaySystemSound ( bravo ) ;

Vous pouvez (enn !) lancer l'application. Des applaudissements vous acclament ! Vous
avez russi jouer votre premier son dans le simulateur. Bien entendu, cette application
fonctionne sans problme sur votre device.
Le
code source se trouve dans le dossier
ecouteAudio.

Copier ce code
B
Code web : 437234


ViewController.h
1
2
3
4
5
6

# import < UIKit / UIKit .h >


# import < AudioToolbox / AudioServices .h >
@interface ViewController : UIViewController
@end

ViewController.m

326

JOUER DES LMENTS AUDIO

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

# import " ViewController . h "


@implementation ViewController
- ( void ) didReceiveMemoryWarning
{
[ super didReceiveMemoryWarning ];
// Release any cached data , images , etc that aren 't in use .
}
# pragma mark - View lifecycle
- ( void ) viewDidLoad
{
[ super viewDidLoad ];
SystemSoundID bravo ;
AudioServicesCreateSystemSoundID ( CFBundleCopyResourceURL (
CFBundleGetMainBundle () , CFSTR ( " Applaudissements " ) , CFSTR (
" caf " ) , NULL ) , & bravo ) ;
AudioServicesPlaySystemSound ( bravo ) ;
}
- ( void ) viewDidUnload
{
[ 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 ];
}

327

CHAPITRE 18.

49
50
51
52
53
54
55

MULTIMDIA : LE SON

- ( BOOL ) shouldAutorotateToInterfaceOrientation :(
UIInterfaceOrientation ) interfaceOrientation
{
// Return YES for supported orientations
return ( interfaceOrientation !=
UIInterfaceOrientationPortraitUpsideDown ) ;
}
@end

La technique AVAudioPlayer
Les iPhone, iPod Touch et iPad disposent de l'application iPod, qui permet d'couter de
la musique et de visualiser des vidos. Les techniques de programmation utilises dans
cette application sont accessibles aux dveloppeurs Objective-C grce (entre autres)
la classe AVAudioPlayer. Cette approche a plusieurs avantages par rapport la
prcdente.
Elle permet :
 de jouer des sons courts ou longs ;
 de jouer des sons compresss, au format MP3 par exemple ;
 d'utiliser plusieurs mthodes pour contrler le son pendant qu'il est jou.
Elle repose sur :
 l'utilisation des frameworks AVFoundation et AudioToolbox ;
 la mise en place du delegate AVAudioPlayerDelegate ;
 la dnition d'un objet AVAudioPlayer ;
 la mise en place de ressources dans l'application pour stocker le chier audio jouer ;
 l'utilisation de mthodes sur l'objet AVAudioPlayer pour contrler le son pendant
qu'il est jou.
Commenons sans plus attendre. Dnissez un nouveau projet bas sur le modle
Single View Application et donnez-lui le nom  audioPlayer .
Insertion des frameworks dans le projet

Ajoutez les frameworks AVFoundation.framework et AudioToolbox.framework dans


le projet. Comme indiqu la gure 18.2, cliquez sur la premire icne ache dans
le volet de navigation (1), basculez sur l'onglet Build Phases dans le volet droit de
Xcode (2), dveloppez l'entre Link Binary With Libraries (3), cliquez sur l'icne
+ (4) et ajoutez les deux frameworks dont nous avons parl.
Dnition de l'objet AVAudioPlayer et mise en place du delegate associ

Cliquez sur ViewController.h dans le volet de navigation et insrez-y deux instructions #import pour faire rfrence aux frameworks que vous avez ajouts dans l'tape
prcdente :
328

JOUER DES LMENTS AUDIO

Figure 18.2  Ajoutez les deux frameworks


1
2

# import < AVFoundation / AVFoundation .h >


# import < AudioToolbox / AudioToolbox .h >

Dnissez la variable d'instance audioPlayer de classe AVAudioPlayer :


1

AVAudioPlayer * audioPlayer ;

Cet objet va vous permettre de jouer des chiers audio quelconques, condition qu'ils
soient compatibles avec les formats audio supports par iOS : AAC, ALAC, HE-AAC,
iLBC, IMA4, Linear PCM, MP3, -law ou a-law.
Pour vous tenir informs des vnements relatifs la lecture du chier audio (position
dans le son, n du son atteint, etc.), mais galement des vnements externes (rception d'un appel tlphonique par exemple), l'application doit implmenter le protocole
AVAudioPlayerDelegate. Pour ce faire, il vous sut d'ajouter ce protocole dans la
dnition de l'interface :
1
2
3
4

@interface ViewController : UIViewController <


AVAudioPlayerDelegate >
{
...
}

Si vous avez suivi mes consignes, le chier ViewController.h doit maintenant ressembler ceci :
1

# import < UIKit / UIKit .h >

329

CHAPITRE 18.

2
3
4
5
6
7
8
9

MULTIMDIA : LE SON

# import < AVFoundation / AVFoundation .h >


# import < AudioToolbox / AudioToolbox .h >
@interface ViewController : UIViewController <
AVAudioPlayerDelegate >
{
AVAudioPlayer * audioPlayer ;
}
@end

Ajout du chier audio dans les ressources

Le chier d'en-ttes tant entirement crit, nous allons passer l'tape suivante en
ajoutant un chier audio dans les ressources de l'application.
Cliquez du bouton droit sur la premire icne ache dans le volet de navigation
et slectionnez New Group dans le menu contextuel. Donnez le nom  Resources  au
nouveau dossier. Ouvrez le Finder et glissez-dposez un chier audio quelconque du
Finder dans le dossier Resources. Au relchement du bouton gauche de la souris, une
bote de dialogue est ache. Assurez-vous que la case Copy items into destination
group's folder soit coche, puis cliquez sur Finish.
Le code de l'application

Il ne reste plus qu' crire le code de l'application.


Cliquez sur ViewController.m dans le volet de navigation. Cette premire approche de
la classe AVAudioPlayer se voulant avant tout pratique, nous allons nous contenter de
jouer un son, sans chercher le contrler. Compltez la mthode viewDidLoad comme
suit :
1
2
3
4
5

- ( void ) viewDidLoad
{
[ super viewDidLoad ];

6
7
8
9
10
11
12
13

330

AudioSessionInitialize ( NULL , NULL , NULL , ( __bridge void *)


self ) ;
UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback ;
AudioSessionSetProperty ( kAudioSessionProperty_AudioCategory ,
sizeof ( sessionCategory ) , & sessionCategory ) ;
NSData * soundFileData ;
soundFileData = [ NSData dataWithContentsOfURL :[ NSURL
fileURLWithPath :[[ NSBundle mainBundle ] pathForResource : @ "
morceau . mp3 " ofType : NULL ]]];
audioPlayer = [[ AVAudioPlayer alloc ] initWithData :
soundFileData error : NULL ];

JOUER DES LMENTS AUDIO

14
15
16
17
18
19
20
21
22
23

if (!([ audioPlayer prepareToPlay ]) )


NSLog ( @ " La m thode prepareToPlay a renvoy la valeur FALSE "
);
audioPlayer . delegate = self ;
[ audioPlayer setVolume : 1 . 0f ];
}

[ audioPlayer play ];

Copier ce code
B
Code web : 585720


La ligne 5 initialise le contexte audio :
1

AudioSessionInitialize ( NULL , NULL , NULL , ( __bridge void *) self


);

Il n'est pas ncessaire de comprendre toutes les subtilits de cette instruction pour
pouvoir l'utiliser. Sachez juste qu'elle doit toujours tre appele avant d'utiliser un
objet AVAudioPlayer.
La ligne 7 dnit l'entier sessionCategory et l'initialise avec la valeur :
1

kAudioSessionCategory_MediaPlayback ;

Si vous vous reportez la documentation Apple, vous verrez que cette constante demande au device de jouer le son dans tous les cas, y compris si le bouton muet est actif,
ou encore si le device passe en mode veille.
La ligne 8 initialise la proprit kAudioSessionProperty_AudioCategory de la session
audio en lui transmettant la valeur dnie dans l'instruction prcdente. Le chier audio
sera donc jou dans tous les cas, y compris quand le bouton muet est actif, ou encore
si le device passe en mode veille :
1

AudioSessionSetProperty ( kAudioSessionProperty_AudioCategory ,
sizeof ( sessionCategory ) , & sessionCategory ) ;

La ligne 9 dnit l'objet soundFileData de classe NSData :


1

NSData * soundFileData ;

Cet objet est utilis pour faire rfrence au chier audio jouer :
1

soundFileData = [ NSData dataWithContentsOfURL :[ NSURL


fileURLWithPath :[[ NSBundle mainBundle ] pathForResource : @ "
morceau . mp3 " ofType : NULL ]]];

Ne vous laissez pas surprendre par l'apparente complexit de cette instruction : elle
se contente de chaner trois messages. Si nous la dcomposons en trois parties bien
distinctes, tout sera bien plus clair.
331

CHAPITRE 18.

MULTIMDIA : LE SON

L'objet soundFileData est initialis (soundFileData =) avec un objet NSData ([NSData


...) qui contient les donnes stockes l'adresse spcie (dataWithContentsOfURL:).
Cette URL se trouve dans le  bundle principal , c'est--dire dans l'application ellemme ([NSBundle mainBundle]).
Le nom du chier est  morceau.mp3  (pathForResource:@"morceau.mp3"). L'extension du chier n'est pas prcise (ofType:NULL]) puisque le nom du chier la contient
dj.
Alors, cette instruction ? Tout fait comprhensible, n'est-ce pas ?
La ligne 13 rserve de la mmoire pour l'objet audioPlayer ([AVAudioPlayer alloc])
et l'initialise avec les donnes qui ont t places dans l'objet soundFileData dans
l'instruction prcdente (initWithData:soundFileData) :
audioPlayer = [[ AVAudioPlayer alloc ] initWithData : soundFileData
error : NULL ];

Le son est prt tre jou. La mthode prepareToPlay le prcharge en mmoire. Si


le prchargement ne s'est pas bien droul, la valeur FALSE est retourne. Dans ce cas,
un message d'erreur est ach dans la console :
1
2

if (!([ audioPlayer prepareToPlay ]) )


NSLog ( @ " La m thode prepareToPlay a renvoy la valeur FALSE " ) ;

L'instruction de la ligne 18 indique que les messages relatifs l'objet audioPlayer


seront traits dans ViewController.m :
audioPlayer . delegate = self ;

Cette instruction aurait tout aussi bien pu ne pas apparatre puisque dans cet
exemple trs simple, aucun des messages relatifs l'objet audioPlayer n'est
trait.

La ligne 20 dnit le volume sonore :


[ audioPlayer setVolume : 1 . 0f ];

La valeur passe la mthode setVolume doit tre comprise entre 0.0f (aucun
son) et 1.0f (volume maximum).

Et enn, la ligne 22 lance la lecture du chier audio :


1

[ audioPlayer play ];

Vous pouvez lancer l'application en cliquant sur l'icne Run. Je vous laisse savourer !
Le code de cette application se trouve dans le dossier audioPlayer.


Copier
ce
code
B
Code web : 682654


332

JOUER DES LMENTS AUDIO

ViewController.h
1
2
3
4
5
6
7
8
9

# import < UIKit / UIKit .h >


# import < AVFoundation / AVFoundation .h >
# import < AudioToolbox / AudioToolbox .h >
@interface ViewController : UIViewController <
AVAudioPlayerDelegate >
{
AVAudioPlayer * audioPlayer ;
}
@end

ViewController.m
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

# import " ViewController . h "


@implementation ViewController
- ( void ) didReceiveMemoryWarning
{
[ super didReceiveMemoryWarning ];
// Release any cached data , images , etc that aren 't in use .
}
# pragma mark - View lifecycle
- ( void ) viewDidLoad
{
[ super viewDidLoad ];
AudioSessionInitialize ( NULL , NULL , NULL , ( __bridge void *)
self ) ;
UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback ;
AudioSessionSetProperty ( kAudioSessionProperty_AudioCategory ,
sizeof ( sessionCategory ) , & sessionCategory ) ;
NSData * soundFileData ;
soundFileData = [ NSData dataWithContentsOfURL :[ NSURL
fileURLWithPath :[[ NSBundle mainBundle ] pathForResource : @ "
morceau . mp3 " ofType : NULL ]]];
audioPlayer = [[ AVAudioPlayer alloc ] initWithData :
soundFileData error : NULL ];
if (!([ audioPlayer prepareToPlay ]) )
NSLog ( @ " La m thode prepareToPlay a renvoy la valeur FALSE "
);
audioPlayer . delegate = self ;

333

CHAPITRE 18.

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

MULTIMDIA : LE SON

[ audioPlayer setVolume : 1 . 0f ];
[ audioPlayer play ];

- ( void ) viewDidUnload
{
[ 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

Un peu plus loin avec la technique AVAudioPlayer


Je ne sais pas pour vous, mais moi, je trouve l'application prcdente un peu  tristounette . Certes, elle joue le chier MP3 la perfection, mais l'cran du device
reste dsesprment vide. Que diriez-vous d'ajouter un arrire-plan l'application, un
contrle de progression pour savoir o en est la lecture du chier et un contrle de
volume pour ajuster le volume sonore comme vous l'entendez ? Tentant non ? Eh bien,
allons-y.
334

JOUER DES LMENTS AUDIO

Commencez par dupliquer le dossier


de l'application
audioPlayer
: cliquez
sur le dos



sier audioPlayer, appuyez sur Command + C , puis sur Command + V et renommezla copie audioPlayer-v2.
Ajout de nouveaux contrles dans la vue

Cliquez sur MainStoryboard.storyboard dans le volet de navigation, puis insrez


trois contrles Label, un contrle Slider et un contrle Progress View dans la vue.
Modiez les dimensions par dfaut de ces contrles, la couleur d'arrire-plan et la
couleur du texte des Label et disposez les contrles dans la vue pour obtenir quelque
chose ressemblant la gure 18.3.

Figure 18.3  Disposez vos contrles comme ceci


Je vous rappelle que vous pouvez modier les caractristiques d'un contrle
en utilisant le volet des utilitaires : si ncessaire, cliquez sur l'icne Hide or
show the Utilities pour faire apparatre le volet des utilitaires, cliquez sur
le contrle dont vous voulez modier les caractristiques, puis sur l'icne Show
the Attributes Inspector pour accder aux caractristiques du contrle.

Dnissez :
 l'outlet dureeTotale pour le premier contrle
 Label ) ;

Label

(celui dans lequel est crit


335

CHAPITRE 18.

MULTIMDIA : LE SON

 l'outlet laPosition pour le contrle Progress


 l'action leVolume pour le contrle Slider.

View ;

Pour ceux qui auraient la mmoire courte, il sut de contrle-glisser-dposer


un contrle depuis la zone d'dition dans le chier d'en-ttes, juste avant
l'instruction @end pour crer un outlet ou une action. Choisissez Outlet ou
Action dans la zone de texte Connection selon l'eet recherch, choisissez
un nom dans la zone Name et cliquez sur Connect.

Pour en terminer avec le chier d'en-ttes, dnissez la variable d'instance playbackTimer


de type NSTimer. Cette variable sera utilise pour mettre jour la position de lecture
dans le contrle Progress View :
NSTimer * playbackTimer ;

Si vous avez suivi mes indications, le chier d'en-ttes devrait ressembler ceci :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# import < UIKit / UIKit .h >


# import < AVFoundation / AVFoundation .h >
# import < AudioToolbox / AudioToolbox .h >
@interface ViewController : UIViewController <
AVAudioPlayerDelegate >
{
AVAudioPlayer * audioPlayer ;
NSTimer * playbackTimer ;
}
@property ( weak , nonatomic ) IBOutlet UILabel * dureeTotale ;
@property ( weak , nonatomic ) IBOutlet UIProgressView * laPosition
;
- ( IBAction ) leVolume :( id ) sender ;
@end

Vous allez maintenant ajouter quelques lignes de code pour donner vie ces contrles.
Mise en place d'un timer

Cliquez sur ViewController.m dans le volet de navigation. Vous allez insrer du code
juste au-dessus de l'instruction [audioPlayer play].
Votre premire action va consister mettre en place un  timer , c'est--dire un
mcanisme qui dclenchera l'excution d'une mthode intervalles rguliers. Cette
mthode sera utilise pour mettre jour le contrle Progress View pendant la lecture
du chier audio :
1
2
3

336

playbackTimer = [ NSTimer scheduledTimerWithTimeInterval : 0 . 5


target : self
selector : @selector ( miseAJour :)

JOUER DES LMENTS AUDIO

4
5

userInfo : nil
repeats : YES ];

Cette instruction initialise l'objet

NSTimer playbackTimer en utilisant la mthode


scheduledTimerWithTimeInterval. Cette dernire demande cinq paramtres.

 La dure entre deux excutions de la mthode, en secondes. Ici 0,5 seconde, soit deux
fois par seconde.
 L'objet dans lequel se trouve la mthode excuter priodiquement. Ici, la valeur
self indique que l'objet se trouve dans l'application.
 Le nom de la mthode excuter. Ici, miseAJour.
 Les informations passer la mthode. Ici, la valeur nil indique qu'aucune information n'est passe la mthode miseAJour.
 La rptition ou la non-rptition de l'excution de la mthode. Ici, la valeur YES
provoque la rptition de la mthode miseAJour jusqu' ce que le timer soit dsactiv.
Achage de la dure totale du chier audio

Vous allez ajouter deux lignes de code dans la mthode viewDidLoad, juste avant le
message [super viewDidLoad];. Pour acher la dure totale du chier audio dans
le Label, commencez par dnir la variable longueur de type float, et stockez-y la
dure totale du chier audio :
1

float longueur = audioPlayer . duration ;

Il ne reste plus qu' acher cette valeur dans le contrle Label


1

dureeTotale

dureeTotale . text = [ NSString stringWithFormat : @ " Dur e totale :


% i secondes " ,( int ) longueur ];

Cette instruction peut paratre un peu complexe pour quelque chose d'aussi simple
qu'acher une valeur dans un Label. Sa longueur s'explique par le fait qu'elle ne
se contente pas de stocker une variable dans une autre. Rappelez-vous : la dure du
chier audio a t stocke dans un nombre virgule (float). Dans un premier temps,
ce nombre est converti en un entier pour supprimer la virgule ((int)longueur), puis
en un NSString ([NSString stringWithFormat:) pour assurer la compatibilit avec
la proprit text du Label.
La mthode viewDidLoad doit maintenant ressembler ceci :
1
2
3
4
5
6
7
8

- ( void ) viewDidLoad
{
AudioSessionInitialize ( NULL , NULL , NULL , ( __bridge void *)
self ) ;
UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback ;
AudioSessionSetProperty ( kAudioSessionProperty_AudioCategory ,
sizeof ( sessionCategory ) , & sessionCategory ) ;
NSData * soundFileData ;

337

CHAPITRE 18.

soundFileData = [ NSData dataWithContentsOfURL :[ NSURL


fileURLWithPath :[[ NSBundle mainBundle ] pathForResource : @ "
morceau . mp3 " ofType : NULL ]]];

9
10
11

audioPlayer = [[ AVAudioPlayer alloc ] initWithData :


soundFileData error : NULL ];

12
13
14

if (!([ audioPlayer prepareToPlay ]) )


NSLog ( @ " La m thode prepareToPlay a renvoy la valeur FALSE "
);

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

MULTIMDIA : LE SON

audioPlayer . delegate = self ;


[ audioPlayer setVolume : 1 . 0f ];
playbackTimer = [ NSTimer scheduledTimerWithTimeInterval : 0 . 5
target : self
selector : @selector ( miseAJour :)
userInfo : nil
repeats : YES ];
[ audioPlayer play ];
float longueur = audioPlayer . duration ;
dureeTotale . text = [ NSString stringWithFormat : @ " Dur e totale
: % i secondes " ,( int ) longueur ];
}

[ super viewDidLoad ];

Copier ce code
B
Code web : 471501

Animation du Progress

View

Vous devez certainement tre presss d'excuter l'application pour voir le contrle
Progress View se mettre jour pendant que le morceau est jou. Mais rchissez un
peu. Ne croyez-vous pas qu'il manque quelque chose pour cela ?
Mais c'est bien sr : la mthode miseAJour ! Voici le code ajouter :
1
2
3
4
5
6

-( void ) miseAJour :( NSTimer *) timer


{
float total = audioPlayer . duration ;
float f = audioPlayer . currentTime / total ;
laPosition . progress = f ;
}

La proprit progress d'un contrle Progress View dnit la position de la barre de


progression. De type float, elle est comprise entre 0.0 (compltement gauche) et
1.0 (compltement droite). Pour dplacer la barre en fonction de la position dans le
338

JOUER DES LMENTS AUDIO

morceau, il sut de diviser la position actuelle par la dure du morceau et de l'aecter


la proprit progress. C'est prcisment ce que fait cette mthode.
Dans un premier temps, la dure totale du morceau est stocke dans la variable float
total :
1

float total = audioPlayer . duration ;

Dans un deuxime temps, la position actuelle (audioPlayer.currentTime) est divise


par la dure du morceau (total) et aecte la variable float f :
1

float f = audioPlayer . currentTime / total ;

Enn, dans un troisime temps, la variable f est aecte la proprit progress du


contrle Progress View, ce qui provoque sa mise jour :
1

laPosition . progress = f ;

Cliquez sur l'icne Run et observez le dplacement de la barre de progression. Impressionnant, non ?
Dtection de la n du son et arrt du timer

Cette courte rcration termine, retournons au code.


Quelques lignes plus tt, nous parlions de la cration d'un timer avec la mthode
scheduledTimerWithTimeInterval. Comme il a t vu, la mthode miseAJour est
excute indniment deux fois par seconde. Vous serez d'accord avec moi : cette mthode n'a plus aucune utilit lorsque le morceau a t entirement jou. C'est pourquoi
nous allons y mettre n ce moment-l.
Une courte recherche dans la documentation Apple montre que la mthode excute
lorsque le morceau est entirement jou, a pour nom audioPlayerDidFinishPlaying.
Une courte recherche dans la documentation Apple ? J'ai recherch et je n'ai
rien trouv ! Puis-je avoir quelques explications ?

Si un vnement est gnr lorsque le morceau a t entirement jou, c'est dans le


protocole AVAudioPlayerDelegate qu'il faut le rechercher. Vous tes d'accord avec
moi ? Ce delegate est en eet en charge de tous les vnements en rapport avec l'objet AVAudioPlayer audioPlayer utilis dans cette application. Pour trouver la mthode excute lorsque le morceau a t entirement jou, j'ai donc tout naturellement
consult l'aide sur le protocole AVAudioPlayerDelegate. Pour cela, j'ai ach le chier
d'en-ttes (1), cliqu sur AVAudioPlayerDelegate (2), puis sur AVAudioPlayerDelegate
Protocol Reference (3), comme la gure 18.4.
Le clic sur AVAudioPlayerDelegate Protocol Reference provoque l'achage de la
fentre d'aide. Quelques secondes susent pour comprendre que la mthode recherche
est audioPlayerDidFinishPlaying.
Aprs cet intermde, dnissez la mthode suivante :
339

CHAPITRE 18.

MULTIMDIA : LE SON

Figure 18.4  Trouver la mthode audioPlayerDidFinishPlaying


1
2
3
4

-( void ) audioPlayerDidFinishPlaying :( AVAudioPlayer *) player


successfully :( BOOL ) flag
{
[ playbackTimer invalidate ];
}

La premire ligne, d'apparence assez complexe, ne fait que reprendre le gabarit de la fonction. Ne vous en faites pas quant sa syntaxe : la fonction
autocomplete de Xcode l'crit pratiquement toute seule au fur et mesure
que vous tapez quelques caractres au clavier.

Lorsque le chier audio a t entirement jou, la mthode invalidate est applique


l'objet playbackTime, ce qui provoque la suppression du timer :
1

[ playbackTimer invalidate ];

Rglage du niveau sonore avec le Slider

Vous allez maintenant donner vie au contrle Slider pour que l'utilisateur puisse rgler
le niveau sonore.
Rappelez-vous : une action de type Value Changed a t dnie pour le contrle
Slider. Chaque fois que la position du curseur sera modie par l'utilisateur, la mthode action correspondante (c'est--dire la mthode leVolume) sera excute. Ajoutez
340

JOUER DES LMENTS AUDIO

les instructions suivantes dans cette mthode :


1
2
3
4
5

- ( IBAction ) leVolume :( id ) sender


{
UISlider * slider = ( UISlider *) sender ;
[ audioPlayer setVolume : slider . value ];
}

La ligne 3 dnit l'objet slider de classe UISlider partir du contrle Slider (sender) :
1

UISlider * slider

= ( UISlider *) sender ;

La ligne 4 applique la mthode setVolume l'objet audioPlayer en lui transmettant


la position du curseur (slider.value) dans le contrle Slider :
1

[ audioPlayer setVolume : slider . value ];

C'est aussi simple que cela. Vous pouvez tester, cela fonctionne parfaitement !
Ajout d'un arrire-plan

Pour terminer en beaut, vous allez ajouter un fond d'cran l'application. Procurezvous une image au format JPG ou PNG de 320 x 480 pixels. Au besoin, redimensionnez
une image existante. Une fois en possession de l'image, faites-la glisser depuis le Finder
vers le dossier Resources de l'application et conrmez son insertion dans les ressources
en cochant la case Copy items into destination group's folder (if needed).
Pour utiliser cette image en arrire-plan de la vue, cliquez sur ViewController.m dans
le volet de navigation et ajoutez la ligne suivante au dbut de la mthode viewDidLoad :
1

self . view . backgroundColor = [[ UIColor alloc ]


initWithPatternImage :[ UIImage imageNamed : @ " arb . jpg " ]];

Dans mon application, l'image s'appelle  arb.jpg  ; ce sera certainement


dirent chez vous, n'oubliez pas de mettre jour votre code en consquence.

Comme vous pouvez le voir, la proprit backgroundColor de l'arrire-plan de la vue


(self.view) est utilise pour acher l'arrire-plan. Cette proprit est initialise avec
une image (initWithPatternImage) nomme  arb.jpg  (imageNamed:@"arb.jpg").
Vous pouvez cliquer sur Run et proter de votre application. La gure 18.5 reprsente
mon rendu nal.
L'application se trouve dans le dossier audioPlayer-v2.


Copier
de
code
B
Code web : 182773


ViewController.h

341

CHAPITRE 18.

MULTIMDIA : LE SON

Figure 18.5  Mon rendu nal


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# import < UIKit / UIKit .h >


# import < AVFoundation / AVFoundation .h >
# import < AudioToolbox / AudioToolbox .h >
@interface ViewController : UIViewController <
AVAudioPlayerDelegate >
{
AVAudioPlayer * audioPlayer ;
NSTimer * playbackTimer ;
}
@property ( weak , nonatomic ) IBOutlet UILabel * dureeTotale ;
@property ( weak , nonatomic ) IBOutlet UIProgressView * laPosition
;
- ( IBAction ) leVolume :( id ) sender ;
@end

ViewController.m
1
2
3
4
5

# import " ViewController . h "

342

@implementation ViewController
@synthesize dureeTotale ;
@synthesize laPosition ;

JOUER DES LMENTS AUDIO

6
7
8
9
10
11
12
13
14
15
16
17
18
19

- ( void ) didReceiveMemoryWarning
{
[ super didReceiveMemoryWarning ];
// Release any cached data , images , etc that aren 't in use .
}
# pragma mark - View lifecycle
- ( void ) viewDidLoad
{
self . view . backgroundColor = [[ UIColor alloc ]
initWithPatternImage :[ UIImage imageNamed : @ " arb . jpg " ]];
AudioSessionInitialize ( NULL , NULL , NULL , ( __bridge void *)
self ) ;

20
21
22

UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback ;


AudioSessionSetProperty ( kAudioSessionProperty_AudioCategory ,
sizeof ( sessionCategory ) , & sessionCategory ) ;

23
24
25

NSData * soundFileData ;
soundFileData = [ NSData dataWithContentsOfURL :[ NSURL
fileURLWithPath :[[ NSBundle mainBundle ] pathForResource : @ "
morceau . mp3 " ofType : NULL ]]];

26
27

audioPlayer = [[ AVAudioPlayer alloc ] initWithData :


soundFileData error : NULL ];

28
29
30

if (!([ audioPlayer prepareToPlay ]) )


NSLog ( @ " La m thode prepareToPlay a renvoy la valeur FALSE "
);

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

audioPlayer . delegate = self ;


[ audioPlayer setVolume : 1 . 0 ];
playbackTimer = [ NSTimer scheduledTimerWithTimeInterval : 0 . 5
target : self
selector : @selector ( miseAJour :)
userInfo : nil
repeats : YES ];
[ audioPlayer play ];
float longueur = audioPlayer . duration ;
dureeTotale . text = [ NSString stringWithFormat : @ " Dur e totale
: % i secondes " ,( int ) longueur ];
}

[ super viewDidLoad ];

343

CHAPITRE 18.

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
88
89
90
91
92
93
94
95
96

MULTIMDIA : LE SON

-( void ) miseAJour :( NSTimer *) timer


{
float total = audioPlayer . duration ;
float f = audioPlayer . currentTime / total ;
laPosition . progress = f ;
}
-( void ) audioPlayerDidFinishPlaying :( AVAudioPlayer *) player
successfully :( BOOL ) flag
{
[ playbackTimer invalidate ];
}
- ( IBAction ) leVolume :( id ) sender
{
UISlider * slider = ( UISlider *) sender ;
[ audioPlayer setVolume : slider . value ];
}
- ( void ) viewDidUnload
{
[ self setDureeTotale : nil ];
[ self setLaPosition : 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 :(

344

ENREGISTREMENT AUDIO

97
98
99

100
101
102

UIInterfaceOrientation ) interfaceOrientation
// Return YES for supported orientations
return ( interfaceOrientation !=
UIInterfaceOrientationPortraitUpsideDown ) ;

@end

Enregistrement audio
Les iPhone, iPod Touch et iPad disposent d'un microphone. Voyons comment l'utiliser
pour crer un dictaphone lmentaire.
Cette application reposera sur l'utilisation du framework AVFoundation, et en particulier de deux de ses classes : AVAudioRecorder (pour l'enregistrement) et AVAudioPlayer
(pour la lecture). Les vnements relatifs aux objets de ces deux classes seront manipuls dans le code de la vue, par l'intermdiaire des delegate AVAudioRecorderDelegate
et AVAudioPlayerDelegate.

Cration du projet
Dnissez un nouveau projet bas sur le modle Single View Application et donnezlui le nom  audioRecorder . Ajoutez le framework AVFoundation au projet. Vous
devriez maintenant savoir le faire, je ne dtaillerai donc pas la manipulation.

Dnition de l'interface et du chier d'en-ttes


Cliquez sur MainStoryboard.storyboard dans le volet de navigation et ajoutez trois
Round Rect Button au projet en faisant apparatre le texte  REC  1 ,  STOP  et
 JOUE  sur ces trois boutons.
Contrle-glissez-dposez tour tour ces trois contrles dans le chier d'en-ttes, juste
au-dessus du @end nal et dnissez (respectivement) les actions enregistre, arrete
et joue pour l'vnement Touch Up Inside.
L'interface est maintenant termine. Jusqu'ici, tout va bien !
Cliquez sur ViewController.h dans le volet de navigation. Comme il a t prcis au
dbut de cette section, cette application va s'appuyer sur les classes AVAudioRecorder
et AVAudioPlayer. Les vnements gnrs par ces deux classes seront grs dans le
code de la vue (ViewController.m).
Ajoutez une instruction #import pour faire rfrence au framework AVFoundation et
une rfrence aux delegate dans la dclaration de l'interface :
1

# import < AVFoundation / AVFoundation .h >


1.  REC  vient de record, qui veut dire  enregistrer  en franais.

345

CHAPITRE 18.

2
3
4
5
6

MULTIMDIA : LE SON

@interface audioRecorderViewController : UIViewController <


AVAudioRecorderDelegate , AVAudioPlayerDelegate >
{
...
}

Pour terminer, dnissez les objets audioRecorder de classe


de classe AVAudioPlayer :

audioPlayer

AVAudioRecorder

et

AVAudioRecorder * audioRecorder ;
AVAudioPlayer * audioPlayer ;

1
2

Le code du chier d'en-ttes devrait maintenant ressembler ceci :


1
2
3
4
5
6
7
8
9
10
11
12
13
14

# import < UIKit / UIKit .h >


# import < AVFoundation / AVFoundation .h >
@interface ViewController : UIViewController <
AVAudioRecorderDelegate , AVAudioPlayerDelegate >
{
AVAudioRecorder * audioRecorder ;
AVAudioPlayer * audioPlayer ;
}
- ( IBAction ) enregistre :( id ) sender ;
- ( IBAction ) arrete :( id ) sender ;
- ( IBAction ) joue :( id ) sender ;
@end

Initialisation de l'objet audioRecorder


Avant de pouvoir lancer l'enregistrement, il faut initialiser l'objet audioRecorder.
Cette opration se fera ds le lancement de l'application, dans la mthode viewDidLoad.
Compltez cette mthode comme suit :
1
2
3
4
5
6
7

- ( void ) viewDidLoad
{
[ super viewDidLoad ];

8
9
10
11

346

NSArray * chemins ;
NSString * cheminDoc ;
chemins = NSSearchPathForDirectoriesInDomains (
NSDocumentDirectory , NSUserDomainMask , YES ) ;
cheminDoc = [ chemins objectAtIndex : 0 ];
NSString * soundFilePath = [ cheminDoc
stringByAppendingPathComponent :@ " monSon . caf " ];
NSDictionary * recordSettings = [ NSDictionary

ENREGISTREMENT AUDIO

dictionaryWithObjectsAndKeys :
[ NSNumber numberWithInt : AVAudioQualityMin ] ,
AVEncoderAudioQualityKey ,
[ NSNumber numberWithInt : 16 ] ,
AVEncoderBitRateKey ,
[ NSNumber numberWithInt : 2 ] ,
AVNumberOfChannelsKey ,
[ NSNumber numberWithFloat : 44100 . 0 ] ,
AVSampleRateKey ,
nil ];

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

NSURL * URLson = [ NSURL fileURLWithPath : soundFilePath ];


NSError * error = nil ;
audioRecorder = [[ AVAudioRecorder alloc ]
initWithURL : URLson
settings : recordSettings
error :& error ];

if ( error ) NSLog ( @" Erreur l ' initialisation de l ' objet


audioRecorder : % @ " , [ error description ]) ;
else [ audioRecorder prepareToRecord ];

Copier ce code
Code web : 397304


Ne soyez pas erays ! Nous allons commenter tout ce code qui, comme vous le verrez,
n'a rien d'insurmontable.
Pour des raisons de scurit, seule une trs petite partie du systme de chier est
accessible en criture sur un device iOS. Chaque application dispose d'un dossier  Documents  dans laquelle elle peut stocker les chiers qu'elle manipule. Pour accder
ce dossier, il faut dans un premier temps connatre son chemin. C'est la raison d'tre
des instructions des lignes 5 9.
On commence par dnir l'objet chemins de classe NSArray, puis l'objet cheminDoc
de classe NSString :
B

NSArray *chemins; NSString *cheminDoc;

Pour trouver le chemin du dossier  Documents , il sut de faire appel la mthode


NSSearchPathForDirectoriesInDomains en lui indiquant que le chemin recherch
concerne le dossier  Documents  :
1

chemins = NSSearchPathForDirectoriesInDomains (
NSDocumentDirectory , NSUserDomainMask , YES ) ;

Cette instruction n'a rien de compliqu : elle se contente de reprendre le gabarit indiqu
dans l'aide :
1
2

NSArray * NSSearchPathForDirectoriesInDomains (
NSSearchPathDirectory directory ,

347

CHAPITRE 18.

3
4
5

);

MULTIMDIA : LE SON

NSSearchPathDomainMask domainMask ,
BOOL expandTilde

en lui indiquant le dossier recherch (NSDocumentDirectory) et l'emplacement de ce


dossier (NSUserDomainMask). La valeur YES pour le paramtre expandTilde indique
que les ventuels tildes dans le chemin doivent tre transforms en un chemin complet.
Une fois de plus, ces informations proviennent de la documentation Apple.
Le NSArray chemins tant initialis, l'instruction suivante extrait la premire information de ce tableau et la stocke dans le NSString cheminDoc. C'est ainsi que cheminDoc
contient le chemin complet du dossier  Documents  de l'application :
cheminDoc = [ chemins objectAtIndex : 0 ];

Le son enregistr sur le device sera stock dans le chier  monSon.caf .


L'instruction suivante (ligne 9) concatne ce nom avec le chemin du dossier  Documents  et stocke le tout dans la variable NSString soundFilePath :
NSString * soundFilePath = [ cheminDoc
stringByAppendingPathComponent :@ " monSon . caf " ];

Arrivs ce point dans le code, nous avons un objet NSString nomm soundFilePath
qui contient le chemin du chier monSon.caf dans lequel le son sera enregistr.
Dans l'tape suivante (lignes 11 21), nous dnissons l'objet recordSettings de type
NSDictionary qui rassemble tous les paramtres en rapport avec l'enregistrement :
1
2
3
4
5
6
7
8
9
10
11

NSDictionary * recordSettings = [ NSDictionary


dictionaryWithObjectsAndKeys :
[ NSNumber numberWithInt : AVAudioQualityMin ] ,
AVEncoderAudioQualityKey ,
[ NSNumber numberWithInt : 16 ] ,
AVEncoderBitRateKey ,
[ NSNumber numberWithInt : 2 ] ,
AVNumberOfChannelsKey ,
[ NSNumber numberWithFloat : 44100 . 0] ,
AVSampleRateKey ,
nil ];

Ce dictionnaire est constitu d'un ensemble de paires objet/cl. Sont ainsi dnis :
 la qualit d'enregistrement : AVEncoderAudioQualityKey, qui est ici initialis
AVAudioQualityMin ;
 la profondeur d'encodage : AVEncoderAudioQualityKey rgl 16 bits ;
 le nombre de canaux d'enregistrement : AVNumberOfChannelsKey pour un enregistrement mono ;
 la frquence d'chantillonnage : AVSampleRateKey rgl sur 22050 Hz.
348

ENREGISTREMENT AUDIO

Ces termes techniques n'orent que peu d'intrt, moins que vous ne soyez
frus d'enregistrement audio. Si vous voulez en savoir plus, je vous suggre
de consulter la page de Wikipdia relative aux frquences d'chantillonnage.
Vous pouvez galement consulter l'aide Apple pour prendre connaissance des
direntes qualits d'enregistrement autorises. Pour cela, reportez-vous la
section  Sample Rate Conversion Audio Quality Flags  de l'aide.


Frquence d'chantillonnage
B
Code web : 228211


Jusqu'ici, nous avons dni l'adresse du chier dans lequel le son sera enregistr et les
paramtres d'enregistrement. Il ne reste plus qu' prparer le device l'enregistrement
en initialisant l'objet audioRecorder. Cette opration va se faire avec la mthode
initWithURL qui demande trois arguments :
 l'adresse du son de type NSURL ;
 le NSDictionary dans lequel se trouvent les paramtres d'enregistrement ;
 un code d'erreur de type NSError.
Nous avons bien l'adresse du son au format NSString. . . mais pas au format NSURL. Il
est donc ncessaire d'eectuer une conversion. Rien de plus simple, grce la mthode
fileURLWithPath :
1

NSURL * URLson = [ NSURL fileURLWithPath : soundFilePath ];

La variable error, de type NSError, est ensuite dnie :


1

NSError * error = nil ;

Nous pouvons (enn !) initialiser l'objet audioRecorder :


1
2
3
4

audioRecorder = [[ AVAudioRecorder alloc ]


initWithURL : URLson
settings : recordSettings
error :& error ];

Si cette initialisation produit une erreur, nous l'achons dans la console :


1

if ( error ) NSLog ( @" Erreur l ' initialisation de l ' objet


audioRecorder : % @ " , [ error description ]) ;

Bien videmment, l'instruction NSLog ne fonctionne que dans le simulateur, et


pas sur les devices. Elle ne servira donc qu' la mise au point de l'application.

Si tout se passe bien lors de l'initialisation, la mthode prepareToRecord est applique


l'objet audioRecorder :
1

else [ audioRecorder prepareToRecord ];

Cette instruction dclenche la cration du chier monSon.caf et informe iOS que l'application est sur le point de lancer un enregistrement.
349

CHAPITRE 18.

MULTIMDIA : LE SON

criture du code pour les Rounded Rect Button


Il ne reste plus qu' crire le code attach aux mthodes action des trois boutons.
Rassurez-vous, cette tche va tre lmentaire.
Reprez la mthode enregistre et compltez-la comme suit :
1
2
3
4

- ( IBAction ) enregistre :( id ) sender


{
[ audioRecorder record ];
}

Comme vous pouvez le voir, pour commencer l'enregistrement, il sut d'appliquer la


mthode record l'objet audioRecorder.
Reprez la mthode arrete et compltez-la comme suit :
1
2
3
4

- ( IBAction ) arrete :( id ) sender


{
[ audioRecorder stop ];
}

Ici encore, le code utilis est trs simple : pour arrter l'enregistrement, il sut d'appliquer la mthode stop l'objet audioRecorder.
Reprez la mthode joue et compltez-la comme suit :
1
2
3
4
5
6
7
8
9
10
11
12
13
14

- ( IBAction ) joue :( id ) sender


{
NSError * error ;
audioPlayer = [[ AVAudioPlayer alloc ]
initWithContentsOfURL : audioRecorder . url
error :& error ];
audioPlayer . delegate = self ;

if ( error )
NSLog ( @ " Error : % @ " , [ error description ]) ;
else
[ audioPlayer play ];

Cette mthode est un peu plus longue, mais elle ne prsente aucune dicult. Aprs
avoir dni la variable error de type NSError :
1

NSError * error ;

l'objet audioPlayer est initialis avec la mthode initWithContentsOfURL :


1
2
3

350

audioPlayer = [[ AVAudioPlayer alloc ]


initWithContentsOfURL : audioRecorder . url
error :& error ];

ENREGISTREMENT AUDIO

L'adresse du chier son est la mme que celle qui a t utilise pour l'enregistrement. Quoi de plus logique, puisque nous voulons jouer le son qui a t
enregistr

L'instruction suivante (ligne 8) indique que les messages en provenance de l'objet


audioPlayer seront traits dans la classe ViewController. Cette instruction n'est
pas vraiment obligatoire, car nous ne traitons aucuns des messages envoys par l'objet
audioPlayer, mais le code est plus  propre  si elle y est insre.
Si l'initialisation de l'objet audioPlayer produit une erreur, elle est ache (dans le
simulateur uniquement) :
1
2

if ( error )
NSLog ( @ " Error : % @ " , [ error description ]) ;

Dans le cas contraire, le son est jou :


1
2

else
[ audioPlayer play ];

Un arrire-plan pour enjoliver l'application

Maintenant que vous savez quel point il est simple d'ajouter un arrire-plan une
vue, pourquoi ne pas en proter pour donner un peu d'allure cette application.
Procurez-vous une image de 320 x 480 pixels. Si ncessaire, redimensionnez une image
existante pour qu'elle ait cette taille. Placez cette image dans les ressources de l'application et ajoutez l'instruction suivante au dbut de la mthode viewDidLoad (dans cet
exemple, l'image a pour nom  fond0.jpg ) :
1

self . view . backgroundColor = [[ UIColor alloc ]


initWithPatternImage :[ UIImage imageNamed : @ " fond0 . jpg " ]];

Lancez l'application sur un device (elle ne fonctionne pas dans le simulateur) et amusezvous enregistrer tout ce qui vous passe par la tte ! Vous trouverez mon rsultat la
gure 18.6.
Pour tous ceux qui se demanderaient d'o provient cette image, il s'agit d'un
clipart d'Oce 2010.

L'application se trouve dans le dossier audioRecorder.




Copier
ce
code
B
Code web : 863307

351

CHAPITRE 18.

MULTIMDIA : LE SON

Figure 18.6  Mon application une fois termine


ViewController.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# import < UIKit / UIKit .h >


# import < AVFoundation / AVFoundation .h >
@interface ViewController : UIViewController <
AVAudioRecorderDelegate , AVAudioPlayerDelegate >
{
AVAudioRecorder * audioRecorder ;
AVAudioPlayer * audioPlayer ;
}
- ( IBAction ) enregistre :( id ) sender ;
- ( IBAction ) arrete :( id ) sender ;
- ( IBAction ) joue :( id ) sender ;
@end

ViewController.m
1
2
3
4

# import " ViewController . h "

352

@implementation ViewController

ENREGISTREMENT AUDIO

5
6
7
8
9
10
11
12
13
14
15
16
17

- ( 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 : @ " fond0 . jpg " ]];

18
19
20
21

NSArray * chemins ;
NSString * cheminDoc ;
chemins = NSSearchPathForDirectoriesInDomains (
NSDocumentDirectory , NSUserDomainMask , YES ) ;
cheminDoc = [ chemins objectAtIndex : 0 ];
NSString * soundFilePath = [ cheminDoc
stringByAppendingPathComponent : @" monSon . caf " ];

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

NSDictionary * recordSettings = [ NSDictionary


dictionaryWithObjectsAndKeys :
[ NSNumber numberWithInt : AVAudioQualityMin ] ,
AVEncoderAudioQualityKey ,
[ NSNumber numberWithInt : 16 ] ,
AVEncoderBitRateKey ,
[ NSNumber numberWithInt : 2 ] ,
AVNumberOfChannelsKey ,
[ NSNumber numberWithFloat : 44100 . 0 ] ,
AVSampleRateKey ,
nil ];
NSURL * URLson = [ NSURL fileURLWithPath : soundFilePath ];
NSError * error = nil ;
audioRecorder = [[ AVAudioRecorder alloc ]
initWithURL : URLson
settings : recordSettings
error :& error ];

if ( error )
NSLog ( @ " Erreur l ' initialisation de l ' objet audioRecorder
: % @ " , [ error description ]) ;
else
[ audioRecorder prepareToRecord ];

353

CHAPITRE 18.

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
88
89
90
91
92
93
94
95
96
97
98

MULTIMDIA : LE SON

- ( void ) viewDidUnload
{
[ 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 ) ;
}
- ( IBAction ) enregistre :( id ) sender
{
[ audioRecorder record ];
}
- ( IBAction ) arrete :( id ) sender
{
[ audioRecorder stop ];
}
- ( IBAction ) joue :( id ) sender
{
NSError * error ;
audioPlayer = [[ AVAudioPlayer alloc ]
initWithContentsOfURL : audioRecorder . url

354

ENREGISTREMENT AUDIO

99
100
101
102
103
104
105
106
107
108

error :& error ];


audioPlayer . delegate = self ;
if ( error )
NSLog ( @ " Error : % @ " , [ error description ]) ;
else
[ audioPlayer play ];

}
@end

En rsum
 Pour jouer des sons sur un device, vous pouvez passer par les  System Sound Services  du framework AudioToolbox. Cette technique est rserve aux sons courts.
Elle est trs simple mettre en uvre.
 Pour jouer des sons sur un device, vous pouvez aussi utiliser un AVAudioPlayer.
Cette technique peut jouer des sons courts ou longs. Elle repose sur l'utilisation des
frameworks AVFoundation et AudioToolbox, mais aussi la mise en place du delegate
AVAudioPlayerDelegate, la dnition d'un objet AVAudioPlayer, la mise en place
de ressources dans l'application pour stocker le chier audio jouer et l'utilisation
de mthodes sur l'objet AVAudioPlayer pour contrler le son pendant qu'il est jou.
 Les iPhone, iPod Touch et iPad disposent d'un microphone. Vous pouvez l'utiliser pour enregistrer des lments audio. Pour cela, vous devez utiliser la classe
AVAudioRecorderDelegate du framework AVFoundation.

355

CHAPITRE 18.

356

MULTIMDIA : LE SON

Chapitre

19

Multimdia : l'image
Dicult :

ue diriez-vous d'exploiter le lecteur vido et l'appareil photo qui se cachent dans


votre device ? Apple a bien fait les choses et ces fonctionnalits sont vraiment aises
manipuler en Objective-C. Dans ce chapitre, je vous propose de dcouvrir comment
insrer un lecteur vido dans vos applications pour lire tout chier vido qui respecte les
standards H.264 et MPEG-4 Part 2. Quelques lignes de code sont susantes ! Pour ne
pas vous arrter en si bon chemin, je vous montrerai ensuite comment prendre des photos
dans une application et les stocker dans l'album photo du device. L encore, il vous sura
d'crire quelques lignes de code !
J'espre vous avoir mis l'eau la bouche. Tournez vite les pages et dcouvrez comment
procder.

357

CHAPITRE 19.

MULTIMDIA : L'IMAGE

Jouer des lments vido


Dans cette section, vous allez dcouvrir comment jouer des vidos sur un device iOS.
Cette prouesse rside dans l'utilisation du framework MediaPlayer, et plus particulirement de la classe MPMoviePlayerController, incluse dans ce framework. La vido
sera joue ds l'excution de l'application.
Crez une nouvelle application base sur le modle Single View Application et
donnez-lui le nom  videoPlayer .
Les chiers d'extension .mov, .mp4, .mpv et .3gp sont supports condition qu'ils
utilisent un des formats de compression suivants :
 H.264 Baseline Profile Level 3.0 video, jusqu' 640 x 480 pixels, 30 images
par seconde ;
 MPEG-4 Part 2 video.

Implmentation du framework MediaPlayer


Avant tout chose, il nous faut ajouter le framework MediaPlayer l'application. Cliquez sur la premire icne du volet de navigation, basculez sur l'onglet Build Phases
et dveloppez la zone Link Binary With Libraries. Cliquez sur l'icne + et ajoutez
le framework MediaPlayer.framework.
Cliquez sur ViewController.h dans le volet de navigation et ajoutez une instruction
import au dbut du chier d'en-ttes pour accder au framework MediaPlayer :
1

# import < MediaPlayer / MediaPlayer .h >

Tant que vous tes dans le chier d'en-ttes, dnissez les variables d'instance lecteur,
de classe MPMoviePlayerController ainsi qu'adresse, de classe NSURL :
MPMoviePlayerController * lecteur ;
NSURL * adresse ;

1
2

Dnissez enn la chane constante cheminComplet et initialisez-la comme suit :


1

# define cheminComplet @ " http :// www . siteduzero . com / uploads / fr /


ftp / iphone / coins - arrondis . mp4 "

Dans cet exemple, la vido provient du site de formation Mediaforma et est


uploade sur le Site du Zro. Libre vous de choisir une autre adresse URL
ou, pourquoi pas, de placer la vido dans les ressources de l'application.

Le chier d'en-ttes devrait maintenant ressembler ceci :


1
2
3

# import < UIKit / UIKit .h >


# import < MediaPlayer / MediaPlayer .h >
# define cheminComplet @ " http :// www . siteduzero . com / uploads / fr /
ftp / iphone / coins - arrondis . mp4 "

358

JOUER DES LMENTS VIDO

4
5
6
7
8
9
10
11

@interface ViewController : UIViewController


{
MPMoviePlayerController * lecteur ;
NSURL * adresse ;
}
@end

Achage en mode paysage


Pour que l'application s'ache en mode paysage par dfaut, vous allez agir sur ses
 informations de dploiement , c'est--dire sur l'cran Summary de l'application.
Comme la gure 19.1, cliquez sur l'entre videoPlayer dans le volet de navigation
(1), slectionnez l'onglet Summary dans la partie centrale de la fentre (2) et demandez
ce que l'application ne s'ache qu'en mode paysage orient gauche. Pour cela, cliquez
sur Landscape Left pour que cette icne apparaisse en noir (3) et, si ncessaire, cliquez
sur Portrait, Upside Down et/ou Landscape Right pour que ces icnes apparaissent
en gris (4).

Figure 19.1  L'application doit s'acher en mode paysage

359

CHAPITRE 19.

MULTIMDIA : L'IMAGE

Implmentation du lecteur
Cette application n'utilise aucun contrle. Interface Builder ne nous sera donc d'aucune utilit. Cliquez directement sur ViewController.m dans le volet de navigation et
modiez la mthode viewDidLoad comme suit :
1
2
3
4
5
6
7
8
9

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
adresse = [[ NSURL alloc ] initWithString : cheminComplet ];
lecteur = [[ MPMoviePlayerController alloc ] initWithContentURL
: adresse ];
lecteur . view . frame = CGRectMake (0 ,0 , 480 , 310 );
[ self . view addSubview : lecteur . view ];
[ lecteur play ];
}

La ligne 4 transforme la chane constante cheminComplet en un objet de classe NSURL


en utilisant la mthode initWithString et l'aecte la variable d'instance adresse :
adresse = [[ NSURL alloc ] initWithString : cheminComplet ];

La ligne 5 initialise la variable d'instance lecteur (c'est--dire notre lecteur vido) en


lui aectant l'adresse URL de la vido jouer :
lecteur = [[ MPMoviePlayerController alloc ] initWithContentURL :
adresse ];

La ligne 6 dnit la taille de la zone dans laquelle sera ache la vido :


lecteur . view . frame = CGRectMake (0 ,0 , 480 , 310 );

Pour ceux qui auraient la mmoire courte, la fonction CGRectMake() retourne


un rectangle dont l'emplacement et les dimensions sont passs en argument.
Les deux premiers paramtres reprsentent l'abscisse et l'ordonne du coin
suprieur gauche du rectangle ; les deux derniers la largeur et la hauteur du
rectangle.

La ligne 7 ajoute la vido la vue courante :


1

[ self . view addSubview : lecteur . view ];

Enn, la ligne 8 dclenche la lecture de la vido :


1

[ lecteur play ];

Et c'est tout ? Cinq instructions susent vraiment pour crer un lecteur vido
sur un device iOS ?

360

JOUER DES LMENTS VIDO

Eh bien oui. Et c'est bien l toute la puissance de la classe MPMoviePlayerController !


Pourquoi ne pas lancer l'application et voir si elle fonctionne. La gure 19.2 reprsente
ce que vous devriez obtenir au bout de quelques secondes (ce temps est ncessaire pour
prcharger la vido qui, rappelons-le, se trouve sur le Web) :

Figure 19.2  La vido est lue dans l'application

Je sens que vous aimeriez aller plus loin avec cette application, c'est pourquoi je vous
propose de lui ajouter un  observateur d'vnements  an de dtecter la n de la
vido.
Bien entendu, il ne s'agit l que d'un prtexte pour ajouter une corde de plus
votre  arc Objective-C . Le principe qui va tre abord ici est une variante
de la gestion vnementielle par delegate. Lorsque vous crerez vos propres
applications, vous pourrez ainsi choisir l'une ou l'autre de ces mthodes pour
rpondre aux vnements retourns par un objet.

Pour dnir un observateur d'vnements, il faut crer un objet NSNotificationCenter


et lui aecter un observateur, associ l'vnement que vous voulez observer. Dans le
cas qui nous intresse, l'vnement  n de la vido  rpond au joli nom de :
1

MPMoviePlayerPlaybackDidFinishNotification

Je n'aurais jamais pu trouver ce nom d'vnement tout seul. Comment savoir


quels vnements sont associs un objet particulier ?

En consultant l'aide Apple de la classe correspondante bien sr. Dans cette section,
nous nous intressons la classe MPMoviePlayerController. C'est donc ici que vous
trouverez les diverses notications mises par ces objets.
Ajoutez l'instruction suivante au dbut de la mthode viewDidLoad :
1

[[ NSNotificationCenter defaultCenter ] addObserver : self selector


: @selector ( playbackFinished :) name :

361

CHAPITRE 19.

MULTIMDIA : L'IMAGE

MPMoviePlayerPlaybackDidFinishNotification object : nil ];

Cette instruction dnit un objet NSNotificationCenter, lui ajoute un observateur


de nom playbackFinished pour rpondre l'vnement :
MPMoviePlayerPlaybackDidFinishNotification

Vous vous en doutez certainement, cette instruction ne se sut pas elle-mme : il


faut lui associer une mthode pour traiter la notication lorsqu'elle sera mise.
Ajoutez le code suivant :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

- ( void ) playbackFinished :( NSNotification *) notification


{
NSNumber * raison = [[ notification userInfo ] objectForKey :
MPMoviePlayerPlaybackDidFinishReasonUserInfoKey ];
switch ([ raison intValue ])
{
case MPMovieFinishReasonPlaybackEnded :
NSLog ( @ " La vid o a t enti rement lue " ) ;
break ;
case MPMovieFinishReasonPlaybackError :
NSLog ( @ " Erreur de lecture " ) ;
break ;
case MPMovieFinishReasonUserExited :
NSLog ( @ " L ' utilisateur a mis fin la vid o " ) ;
break ;
default :
break ;
}
}

Que diriez-vous de dtailler un peu ce code ? La ligne 3 rcupre la valeur associe la cl MPMoviePlayerPlaybackDidFinishReasonUserInfoKey. Cette cl donne
la raison ayant provoqu la n de la vido. En cliquant dans la fentre d'aide sur
MPMoviePlayerPlaybackDidFinishReasonUserInfoKey puis sur MPMovieFinishReason,
on obtient les direntes valeurs possibles pour cette cl (gure 19.3).
Les instructions suivantes testent la valeur de la cl et achent un message en consquence dans la console. Bien videmment, ils ne produiront aucun eet sur un device
rel.
Les chiers de cette application se trouvent dans le dossier videoPlayer.


Copier ce code
B
Code web : 741683


ViewController.h
1
2
3

# import < UIKit / UIKit .h >


# import < MediaPlayer / MediaPlayer .h >

362

JOUER DES LMENTS VIDO

Figure 19.3  Les direntes valeurs possibles pour la cl

363

CHAPITRE 19.

4
5
6
7
8
9
10
11
12

MULTIMDIA : L'IMAGE

# define cheminComplet @ " http :// www . siteduzero . com / uploads / fr /


ftp / iphone / coins - arrondis . mp4 "
@interface ViewController : UIViewController
{
MPMoviePlayerController * lecteur ;
NSURL * adresse ;
}
@end

ViewController.m
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

# import " ViewController . h "


@implementation ViewController
- ( void ) didReceiveMemoryWarning
{
[ super didReceiveMemoryWarning ];
// Release any cached data , images , etc that aren 't in use .
}
# pragma mark - View lifecycle
- ( void ) playbackFinished :( NSNotification *) notification
{
NSNumber * raison = [[ notification userInfo ] objectForKey :
MPMoviePlayerPlaybackDidFinishReasonUserInfoKey ];
switch ([ raison intValue ])
{
case MPMovieFinishReasonPlaybackEnded :
NSLog ( @ " La vid o a t enti rement lue " ) ;
break ;
case MPMovieFinishReasonPlaybackError :
NSLog ( @ " Erreur de lecture " ) ;
break ;
case MPMovieFinishReasonUserExited :
NSLog ( @ " L ' utilisateur a mis fin la vid o " ) ;
break ;
default :
break ;
}
}
- ( void ) viewDidLoad
{
[ super viewDidLoad ];

364

JOUER DES LMENTS VIDO

[[ NSNotificationCenter defaultCenter ] addObserver : self


selector : @selector ( playbackFinished :) name :
MPMoviePlayerPlaybackDidFinishNotification object : nil ];

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

adresse = [[ NSURL alloc ] initWithString : cheminComplet ];


lecteur = [[ MPMoviePlayerController alloc ] initWithContentURL
: adresse ];
lecteur . view . frame = CGRectMake (0 ,0 , 480 , 310 ) ;
[ self . view addSubview : lecteur . view ];
[ lecteur play ];

- ( void ) viewDidUnload
{
[ 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 ( interfaceOrientation !=
UIInterfaceOrientationLandscapeRight ) ;
}
@end

365

CHAPITRE 19.

MULTIMDIA : L'IMAGE

Prendre des photos


Dans un chapitre prcdent, vous avez appris utiliser un objet pour choisir des images
dans l'album photo et les acher sur l'cran. Nous allons nous appuyer sur ce projet
pour manipuler l'appareil photo contenu dans un device iOS. Aprs validation par
l'utilisateur, les photos seront stockes dans l'album photo.

Cration du projet
Dnissez un nouveau projet bas sur le modle Single View Application et donnezlui le nom  appPhoto .
Une fois le projet cr, cliquez sur MainStoryboard.storyboard dans le volet de navigation, puis ajoutez un contrle Rounded Rect Button et un contrle Label. Doublecliquez sur le Rounded Rect Button et donnez-lui le nom  Prendre une photo .
Double-cliquez sur le contrle Label et tapez  Appuyez sur le bouton pour prendre
une photo .
Redimensionnez et repositionnez ces contrles pour obtenir quelque chose ressemblant
la gure 19.4.

Figure 19.4  Disposez vos contrles de cette manire

Vous allez maintenant ajouter une image de fond d'cran au projet. Je vous rappelle
que cette image doit faire 320 x 480 pixels.
366

PRENDRE DES PHOTOS

Cliquez du bouton droit sur l'icne appPhoto, ache dans la partie suprieure du
volet de navigation et slectionnez New Group dans le menu contextuel. Renommez le
nouveau dossier  Resources  et faites glissez l'image utiliser en fond d'cran depuis
le nder jusqu'au dossier Resources du volet de navigation.
la n du glisser-dposer, lorsque vous relchez le bouton gauche de la souris, une bote
de dialogue intitule Choose options for adding these files est ache. Assurezvous que la case Copy items into destination group's folder est coche (ainsi,
l'image sera copie dans l'application), puis cliquez sur Finish.
Une fois l'image insre dans les ressources, le volet de navigation devrait ressembler
la gure 19.5.

Figure 19.5  Le volet de navigation du projet

Liaison des contrles au code


Vous allez maintenant relier les contrles Label et Rounded Rect Button au code.
En crant :
 un outlet pour le contrle Label, il sera possible d'acher le nombre de photos prises
avec l'application ;
 une action pour le Rounded Rect Button, il sera possible de dclencher l'appareil
photo sur un simple clic de l'utilisateur.
Cliquez sur Show the Assistant editor dans la barre d'outils de Xcode, puis contrleglissez-dposez le Label de la zone d'dition dans le chier ViewController.h, juste
au-dessus du @end nal et crez l'outlet infos.
Contrle-glissez-dposez le Rounded Rect Button de la zone d'dition dans le chier
ViewController.h, juste au-dessus du @end nal et crez l'action prendPhoto, dclenche sur l'vnement Touch Up Inside.
Cette application va utiliser un UIImagePickerController (ncessaire pour la prise de
vues) et un compteur de prises de vues. Pour mettre en place ces deux objets, dnissez
les variables d'instance suivantes :
1

UIImagePickerController * picker ;

367

CHAPITRE 19.

MULTIMDIA : L'IMAGE

int compteur ;

Si vous avez suivi mes consignes, le chier d'en-ttes devrait avoir l'allure suivante :
1
2
3
4
5
6
7
8
9
10
11
12

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
{
UIImagePickerController * picker ;
int compteur ;
}
@property ( weak , nonatomic ) IBOutlet UILabel * infos ;
- ( IBAction ) prendPhoto :( id ) sender ;
@end

criture du code de l'application


Vous allez maintenant modier le code de l'application. Cliquez sur ViewController.m
dans le volet de navigation et compltez la mthode viewDidLoad comme suit :
1
2
3
4
5
6

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
self . view . backgroundColor = [[ UIColor alloc ]
initWithPatternImage :[ UIImage imageNamed : @" fond - ap - photo .
jpg " ]];
compteur = 0;
}

L'instruction de la ligne 4 indique que l'application utilisera l'image fond-ap-photo.jpg


en arrire-plan de l'application.
L'instruction de la ligne 5 initialise la variable int compteur 0. Cette variable sera
utilise pour comptabiliser le nombre de photos prises dans l'application. Il est donc
tout fait normal de l'initialiser 0 au lancement de l'application.
Vous allez maintenant dnir les instructions excuter lorsque l'utilisateur appuie sur
le Rounded Rect Button. Localisez la mthode prendPhoto et compltez-la comme
suit :
1
2
3
4
5
6
7

- ( IBAction ) prendPhoto :( id ) sender


{
picker = [[ UIImagePickerController alloc ] init ];
picker . delegate = self ;
picker . sourceType = UIImagePickerControllerSourceTypeCamera ;
[ self presentModalViewController : picker animated : YES ];
}

368

PRENDRE DES PHOTOS

L'instruction de la ligne 3 dnit l'objet UIImagePickerController


tialise :
1

picker

et l'ini-

picker = [[ UIImagePickerController alloc ] init ];

L'instruction de la ligne 4 indique que les vnements lis l'UIImagePickerController


seront grs dans cette classe.
1

picker . delegate = self ;

La ligne 5 indique que les donnes manipules par l'UIImagePickerController proviendront de l'appareil photo :
1

picker . sourceType = UIImagePickerControllerSourceTypeCamera ;

Enn, la ligne 6 dnit le mode d'achage de l'UIImagePickerController :


1

[ self presentModalViewController : picker animated : YES ];

Encore une fois, ces instructions ne viennent pas de mon imagination prolixe, mais plutt de l'aide Apple sur le protocole
UIImagePickerControllerDelegate et sur la classe UIViewController.
Si vous le souhaitez, je vous invite parcourir ces deux pages d'aide pour
approfondir le sujet.

Il se peut qu'un triangle  Attention  de couleur jaune soit ach en face de l'instruction picker.delegate = self;. Si tel est le cas, cliquez dessus pour prendre connaissance du problme. Voici ce qui est ach :
Assigning to 'id < UINavigationControllerDelegate .
UIImagePickerControllerDelegate >' from incompatible type '
appPhotoViewController * '

Ce type d'erreur a dj t rencontr dans ce livre. Il signie que vous devez ajouter
un delegate (un gestionnaire d'vnements) pour UINavigationControllerDelegate
et UIImagePickerControllerDelegate.
Retournez dans le chier ViewController.h et modiez la dclaration de l'interface
comme suit :
1
2
3
4

@interface appPhotoViewController : UIViewController <


UINavigationControllerDelegate ,
UIImagePickerControllerDelegate >
{
...
}

Vous pouvez retourner dans le chier ViewController.m et constater que l'avertissement a disparu.
Puisque nous venons d'indiquer que les vnements gnrs par UIImagePickerController
vont tre grs dans la classe appPhoto, nous allons crire le code correspondant aux
369

CHAPITRE 19.

MULTIMDIA : L'IMAGE

deux vnements susceptibles de se produire : didFinishPickingMediaWithInfo et


imagePickerControllerDidCancel.
Une fois encore, ces deux vnements ont t trouvs dans l'aide Apple, dans
la section consacre au protocole UIImagePickerControllerDelegate.
Quoi de plus normal, puisque nous nous intressons aux vnements gnrs
par un UIImagePickerController ?

Commencez par dnir la mthode didFinishPickingMediaWithInfo :


1
2
3
4
5
6

- ( void ) imagePickerController :( UIImagePickerController *)


Picker didFinishPickingMediaWithInfo :( NSDictionary *) info
{
UIImage * img = [ info objectForKey :
UIImagePickerControllerOriginalImage ];
UIImageWriteToSavedPhotosAlbum ( img , self , @selector ( image :
didFinishSavingWithError : contextInfo :) , nil ) ;
[[ Picker parentViewController ]
dismissModalViewControllerAnimated : YES ];
}

Lorsqu'une photo a t prise, la mthode didFinishPickingMediaWithInfo est excute et l'objet info de classe NSDictionary lui est transmis. La photo se trouve dans
la cl UIImagePickerControllerOriginalImage de l'objet info. Pour la rcuprer,
on envoie un message l'objet info ([info...) en lui demandant d'accder la cl
(objectForKey:) UIImagePickerControllerOriginalImage. Cet objet est mmoris
dans l'objet img de classe UIImage :
UIImage * img = [ info objectForKey :
UIImagePickerControllerOriginalImage ];

On utilise la mthode UIImageWriteToSavedPhotosAlbum pour sauvegarder la photo


dans l'album photo :
UIImageWriteToSavedPhotosAlbum ( img , self , @selector ( image :
didFinishSavingWithError : contextInfo :) , nil ) ;}

Quatre paramtres sont transmis cette mthode.


1. La photo : img.
2. L'objet pour lequel une mthode sera excute aprs la sauvegarde dans l'album.
Le mot self signie que la mthode appeler se trouve dans la classe.
3. Le nom de la mthode excuter lorsque la sauvegarde dans l'album a t faite :
@selector(image:didFinishSavingWithError:contextInfo:).
4. Un ventuel pointeur vers des donnes passer la mthode : nil. Ici, aucun
pointeur n'est pass.
La dernire instruction supprime la vue de la photo qui vient d'tre prise :
370

PRENDRE DES PHOTOS

[[ Picker parentViewController ]
dismissModalViewControllerAnimated : YES ];

Lorsqu'une photo a t prise, l'utilisateur peut annuler sa sauvegarde dans l'album en


appuyant sur le bouton Cancel. La mthode imagePickerControllerDidCancel est
alors excute :
1
2
3
4

- ( void ) imagePickerControllerDidCancel :( UIImagePickerController


*) Picker
{
[[ Picker parentViewController ]
dismissModalViewControllerAnimated : YES ];
}

L'instruction contenue dans cette mthode a dj t rencontre dans la mthode prcdente, didFinishPickingMediaWithInfo. Elle supprime la vue de la photo qui vient
d'tre prise.
Rappelez-vous, dans la mthode didFinishPickingMediaWithInfo, on a utilis la mthode UIImageWriteToSavedPhotosAlbum pour enregistrer la photo qui vient d'tre
prise dans l'album photo. Dans cette mthode, nous avons indiqu que la mthode
didFinishSavingWithError devait tre excute juste aprs la sauvegarde dans l'album photo. Pour en terminer avec le code, il reste donc crire cette mthode :
1
2
3
4
5
6
7
8

- ( void ) image :( UIImage *) image didFinishSavingWithError :(


NSError *) error contextInfo :( void *) contextInfo
{
compteur ++;
if ( compteur == 1 )
infos . text = @ " 1 photo ajout e l ' album photo " ;
else
infos . text = [ NSMutableString stringWithFormat : @" % i % @ " ,
compteur , @ " photos ajout es l ' album photo . " ];
}

Cette mthode est utilise pour modier le texte ach dans le contrle Label. Aprs
avoir incrment le compteur de prises de vues avec compteur++;, la valeur du compteur
est teste. Si une seule photo a t prise, le contrle Label est mis jour comme suit :
1
2

if ( compteur == 1 )
infos . text = @ " 1 photo ajout e l ' album photo " ;

Si le compteur est dirent de 1, cela signie que plusieurs photos ont t prises. Le
message est donc lgrement dirent :
1
2

else
infos . text = [ NSMutableString stringWithFormat : @" % i % @ " ,
compteur , @ " photos ajout es l ' album photo . " ];

Comme vous le voyez, le texte ach dans le Label (infos.text) est obtenu en
crant un objet NSMutableString ([NSMutableString ...) dans lequel on concatne
(stringWithFormat:) un entier et une chane (@"%i %@"). L'entier est la valeur de
371

CHAPITRE 19.

MULTIMDIA : L'IMAGE

la variable compteur. La chane est spcie dans le troisime paramtre (@"photos


ajoutes l'album photo.").
L'application est entirement fonctionnelle. Bien entendu, elle ne peut s'excuter que
sur un device rel. Si vous essayez de prendre une photo dans le simulateur iOS, une
erreur sera ache dans la console et l'application prendra n.
Cette application se trouve dans le dossier appPhoto.


Copier ce code
B
Code web : 497045


ViewController.h
1
2
3
4
5
6
7
8
9
10
11
12

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController <
UINavigationControllerDelegate ,
UIImagePickerControllerDelegate >
{
UIImagePickerController * picker ;
int compteur ;
}
@property ( weak , nonatomic ) IBOutlet UILabel * infos ;
- ( IBAction ) prendPhoto :( id ) sender ;
@end

ViewController.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# import " ViewController . h "


@implementation ViewController
@synthesize infos ;
- ( 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 : @" fond - ap - photo .
jpg " ]];
compteur = 0;

372

PRENDRE DES PHOTOS

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

}
- ( void ) imagePickerController :( UIImagePickerController *)
Picker didFinishPickingMediaWithInfo :( NSDictionary *) info
{
UIImage * img = [ info objectForKey :
UIImagePickerControllerOriginalImage ];
UIImageWriteToSavedPhotosAlbum ( img , self , @selector ( image :
didFinishSavingWithError : contextInfo :) , nil ) ;
[[ Picker parentViewController ]
dismissModalViewControllerAnimated : YES ];
}
- ( void ) image :( UIImage *) image didFinishSavingWithError :(
NSError *) error contextInfo :( void *) contextInfo
{
compteur ++;
if ( compteur == 1 )
infos . text = @ " 1 photo ajout e l ' album photo " ;
else
infos . text = [ NSMutableString stringWithFormat : @" % i % @ " ,
compteur , @ " photos ajout es l ' album photo . " ];
}
- ( void ) viewDidUnload
{
[ self setInfos : nil ];
[ super viewDidUnload ];
// Release any retained subviews of the main view .
// e . g . self . myOutlet = nil ;
}
- ( void ) imagePickerControllerDidCancel :( UIImagePickerController
*) Picker
{
[[ Picker parentViewController ]
dismissModalViewControllerAnimated : YES ];
}
- ( void ) viewWillAppear :( BOOL ) animated
{
[ super viewWillAppear : animated ];
}
- ( void ) viewDidAppear :( BOOL ) animated
{
[ super viewDidAppear : animated ];
}
- ( void ) viewWillDisappear :( BOOL ) animated

373

CHAPITRE 19.

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

{
}

MULTIMDIA : L'IMAGE

[ super viewWillDisappear : animated ];

- ( void ) viewDidDisappear :( BOOL ) animated


{
[ super viewDidDisappear : animated ];
}
- ( BOOL ) shouldAutorotateToInterfaceOrientation :(
UIInterfaceOrientation ) interfaceOrientation
{
// Return YES for supported orientations
return ( interfaceOrientation !=
UIInterfaceOrientationPortraitUpsideDown ) ;
}
- ( IBAction ) prendPhoto :( id ) sender
{
picker = [[ UIImagePickerController alloc ] init ];
picker . delegate = self ;
picker . sourceType = UIImagePickerControllerSourceTypeCamera ;
[ self presentModalViewController : picker animated : YES ];
}
@end

En rsum
 Pour jouer des vidos sur un device, vous utiliserez le framework MediaPlayer, et plus
particulirement la classe MPMoviePlayerController, incluse dans ce framework.
 La mthode play dclenche la lecture de la vido.
 L'vnement MPMoviePlayerPlaybackDidFinishNotification permet de se tenir
inform sur l'tat de la vido (erreur de lecture, arrt par l'utilisateur, vido entirement lue).
 Les chiers d'extension .mov, .mp4, .mpv, et .3gp sont supports, condition qu'ils
utilisent un des formats de compression H.264 Baseline Profile Level 3.0 video
ou MPEG-4 Part 2 video.
 L'objet UIImagePickerController permet de choisir des images dans l'album photo
et de les acher sur l'cran.
 En aectant la valeur UIImagePickerControllerSourceTypeCamera la proprit
sourceType d'un tel objet, il est trs simple de prendre des photos partir d'une application. Une fois la photo prise, la mthode didFinishPickingMediaWithInfo est
excute. Il sut alors d'utiliser la mthode UIImageWriteToSavedPhotosAlbum :
UIImageWriteToSavedPhotosAlbum pour sauvegarder la photo dans l'album photo.

374

Chapitre

20

Acclromtre
Dicult :

es iPhone, iPod Touch et iPad sont quips d'un acclromtre qui leur permet de
dterminer leur orientation par rapport au sol. Dans ce chapitre, je vais vous montrer
comment utiliser les donnes renvoyes par l'acclromtre pour acher l'inclinaison
du device et dtecter s'il a t agit.
Cela vous tente ? Allons-y de ce pas !

375

CHAPITRE 20.

ACCLROMTRE

Mise en place de l'application


Avant de commencer
Les acclrations dtectes par l'acclromtre consistent en trois valeurs ottantes qui
reprsentent les trois axes du device, comme indiqu la gure 20.1.

Figure 20.1  Les trois axes du device

Pour obtenir ces informations, vous utiliserez la classe UIAccelerometer. Un coup


d'il l'aide Apple montre que les vnements gnrs par les objets de cette classe se
font via le protocole UIAccelerometerDelegate. Un autre coup d'il l'aide Apple
sur le protocole UIAccelerometerDelegate montre que la mthode vnementielle
utiliser pour recevoir les donnes relatives l'acclration est didAccelerate.
Il ne reste plus qu' implmenter un objet de la classe UIAccelerometer et grer les
vnements renvoys par cet objet dans la mthode didAccelerate pour connatre la
position du device.

Dnition de l'interface de l'application


Dnissez un nouveau projet de type Single View Application et donnez-lui le nom
 accelerometre .
Une fois le projet cr, cliquez sur MainStoryboard.storyboard dans le volet de navigation. Ajoutez un contrle Label la vue de l'application. Double-cliquez dessus
et tapez  Acclromtre  au clavier. Choisissez une police votre convenance et un
corps lev pour que ce Label fasse oce de titre (pour l'exemple, j'ai choisi une police
Helvetica de corps 43).
Pour modier la police et le corps du Label, cliquez sur le Label dans le
canevas (1), achez l'inspecteur des attributs en cliquant sur l'icne Show
the Attributes inspector dans le volet des utilitaires (2), puis agissez
sur le paramtre Font (3), comme indiqu la gure 20.2.

376

MISE EN PLACE DE L'APPLICATION

Figure 20.2  Vous pouvez modier la police et le corps du Label

Insrez quatre autres Label dans la partie infrieure de la vue. Dplacez-les et alignezles pour obtenir quelque chose ressemblant la gure 20.3.

Figure 20.3  Ajoutez des Label et disposez-les de la sorte

377

CHAPITRE 20.

ACCLROMTRE

Liaison des contrles au code


Pour que l'application puisse acher des informations dans les quatre derniers Label,
vous devez tablir un lien entre l'interface et le code.
Achez cte cte la zone d'dition et le chier ViewController.h en cliquant sur
l'icne Show the Assistant editor dans la barre d'outils.
Contrle-glissez-dposez tour tour les quatre derniers Label et dnissez les outlets
x, y, z et mouvement. Le chier ViewController.h doit maintenant ressembler ceci :
1
2
3
4
5
6
7
8
9

# import < UIKit / UIKit .h >


@interface ViewController :
@property ( weak , nonatomic )
@property ( weak , nonatomic )
@property ( weak , nonatomic )
@property ( weak , nonatomic )

UIViewController
IBOutlet UILabel
IBOutlet UILabel
IBOutlet UILabel
IBOutlet UILabel

*x;
*y;
*z;
* mouvement ;

@end

criture du code
L'interface et le chier d'en-ttes tant dnis, 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 arrire-plan l'application. Dnissez
un dossier Resources dans l'arborescence de l'application, procurez-vous une image de
320 x 480 pixels et ajoutez-la ce dossier.
Pour que l'image d'arrire-plan s'ache ds l'ouverture de l'application, ajoutez l'instruction suivante dans la mthode viewDidLoad (cette instruction suppose que l'image
d'arrire-plan a pour nom  gyro.jpg ) :
1

self . view . backgroundColor = [[ UIColor alloc ]


initWithPatternImage :[ UIImage imageNamed : @" gyro . jpg " ]];

Vous allez maintenant dnir un objet de classe UIAccelerometer et l'initialiser. Compltez la mthode viewDidLoad comme suit :
1
2
3
4
5
6
7
8

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

378

CRITURE DU CODE

la ligne 5, nous dnissons l'objet testAccel de type UIAccelerator. Cet objet est
initialis avec la mthode sharedAccelerometer, comme indiqu dans la documentation Apple :
1

UIAccelerometer * testAccel = [ UIAccelerometer


sharedAccelerometer ];

La ligne 6 indique que les vnements relatifs l'objet testAccel seront traits dans
la classe courante, c'est--dire dans la classe de la vue :
1

testAccel . delegate = self ;

la ligne 7, nous utilisons la proprit updateInterval pour dnir la priode de la


mise jour des donnes fournies par l'acclromtre. Ici, tous les 1/10 seconde :
1

testAccel . updateInterval = 0 . 1f ;

Enn, la ligne 8 ache le message  Le device est calme  dans le Label


pour indiquer que le device n'est pas agit :
1

mouvement

[ mouvement setText : @ " Le device est calme " ];

Si je me souviens de ce qui a t dit au dbut de cette section, il est ncessaire d'implmenter le protocole UIAccelerometerDelegate. Est-ce qu'il ne
faudrait pas agir sur le chier d'en-ttes pour cela ?

Tout fait exact. D'ailleurs, le message d'avertissement ach en face de la ligne


testAccel.delegate = self; (gure 20.4) le conrme :

Figure 20.4  Un message d'erreur apparat

Cliquez sur ViewController.h dans le volet de navigation et ajoutez la rfrence au


delegate dans l'instruction @interface :
1
2
3
4

@interface accelerometreViewController : UIViewController <


UIAccelerometerDelegate >
{
...
}

En consultant la documentation Apple relative UIAccelerometerDelegate, vous


verrez que la mthode didAccelerate est appele lorsque de nouvelles donnes issues
de l'acclromtre sont disponibles. Dnissez cette mthode comme suit :
379

CHAPITRE 20.

1
2
3
4
5
6
7
8
9
10

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

11
12
13
14
15
16
17
18
19
20
21

ACCLROMTRE

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 mchant dans cette mthode !


Si le gabarit de la mthode vous semble compliqu, sachez qu'il a t automatiquement
propos par Xcode ds la saisie du mot accelerometer, comme le montre la gure
20.5.

Figure 20.5  Xcode vous propose automatiquement le gabarit de la mthode

Les acclrations selon les axes X, Y et Z sont accessibles dans les proprits x, y et
de l'objet acceleration. L'instruction de la ligne 3 teste si l'acclration du device
est suprieure 1,5 selon un des axes :
z
1

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 ach en consquence dans le Label
mouvement :
380

CRITURE DU CODE

[ 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'acclration peut en eet tre ngative. En la privant de son signe, il est plus
facile de tester si elle dpasse une certaine limite et ainsi dcrter 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
ncessaire de mettre en place un artice pour que le texte  J'ai dtect une secousse 
reste ach plus longtemps, sans quoi il sera pratiquement impossible de le voir. C'est
le rle des deux instructions qui suivent :
1
2

if ( temporisation == 0 )
temporisation = 1 ;

La variable temporisation vaut 0 par dfaut. 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 achent les valeurs des acclrations dans les labels x, y et z :
1
2
3

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 faon trs classique,
la mthode stringWithFormat est utilise pour concatner deux lments (ici, un texte
et un ottant) et les convertir en un NSString.
Le bloc d'instructions suivant est plus intressant. C'est lui qui se charge d'acher le
texte  J'ai dtect une secousse  pendant trois secondes. Si la variable temporisation
est suprieure 0, on l'incrmente :
1
2

if ( temporisation > 0 )
temporisation ++;

Si elle a pour valeur 30, ou en d'autres termes, si elle est passe une trentaine de fois
par ce code (28 exactement), cela signie qu'environ 3 secondes se sont coules depuis
l'achage du texte  J'ai dtect une secousse  dans le Label :
1

if ( temporisation == 30 )

Dans ce cas, le texte  Le device est calme  est ach dans ce mme Label et la
variable temporisation est mise 0, en attendant que le device soit agit une nouvelle
fois :
1
2

[ mouvement setText : @ " Le device est calme " ];

381

CHAPITRE 20.

3
4

ACCLROMTRE

temporisation = 0 ;

Pour que ce code fonctionne, deux petites lignes doivent tre ajoutes.
La variable temporisation doit tre initialise 0 dans la mthode viewDidLoad :
1
2
3
4
5
6

- ( void ) viewDidLoad
{
...
temporisation = 0 ;
...
}

La variable temporisation doit tre dclare dans le chier d'en-ttes :


1
2
3
4
5

@interface accelerometreViewController : UIViewController <


UIAccelerometerDelegate >
{
...
int temporisation ;
}

a y est, l'application est entirement fonctionnelle. Vous pouvez la lancer (pas dans
le simulateur, videmment !). La gure 20.6 reprsente ce que j'ai obtenu.

Figure 20.6  Mon application est termine et fonctionnelle

Cette application se trouve dans le dossier accelerometre.


382

CRITURE DU CODE

Copier ce code
B
Code web : 370619

ViewController.h
1
2
3
4
5
6
7
8
9
10
11
12
13

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController <
UIAccelerometerDelegate >
{
int temporisation ;
}
@property
@property
@property
@property

( weak ,
( weak ,
( weak ,
( weak ,

nonatomic )
nonatomic )
nonatomic )
nonatomic )

IBOutlet
IBOutlet
IBOutlet
IBOutlet

UILabel
UILabel
UILabel
UILabel

*x ;
*y ;
*z ;
* mouvement ;

@end

ViewController.m
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

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

383

CHAPITRE 20.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

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

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

ACCLROMTRE

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

384

CRITURE DU CODE

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

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

En rsum
 Les acclrations dtectes par l'acclromtre consistent en trois valeurs ottantes
qui reprsentent les trois axes du device. Pour obtenir ces informations, vous utiliserez
la classe UIAccelerometer.
 Dnissez un objet de classe UIAccelerometer, dnissez la priode de mise
jour des informations le concernant avec la proprit updateInterval et utilisez
la mthode didAccelerate pour obtenir les valeurs instantanes de l'acclration
(acceleration.x, acceleration.y et acceleration.z).
 Pour dtecter une secousse sur le device, il sut que l'une des composantes d'acclration renvoyes par l'objet acceleration soit suprieure une valeur donne (1,5
par exemple).

385

CHAPITRE 20.

386

ACCLROMTRE

Chapitre

21

Un jeu de casse-briques
Dicult :

ans ce chapitre, vous allez apprendre crer un jeu de casse-briques. Ce classique


du genre va vous montrer de nombreuses techniques propres aux jeux et ainsi vous
prparer pour le prochain chapitre, qui sera un TP sur la cration d'un autre jeu.
Mais revenons ce chapitre.
Vous apprendrez entre autres :
 dnir et animer des objets anims ;
 dtecter des collisions ;
 eectuer des boucles de traitement ;
 utiliser une musique de fond ;
 utiliser des bruitages.
J'espre vous avoir mis l'eau la bouche. Passez vite la suite et commenons sans
attendre !

387

CHAPITRE 21.

UN JEU DE CASSE-BRIQUES

Avant toute chose, je vais vous montrer quoi va ressembler l'application que nous
allons raliser. Pour cela, regardez la gure 21.1. J'espre qu'elle vous plat.

Figure 21.1  Le casse-briques que nous allons raliser

Dnition de l'interface
Lancez Xcode, dnissez un nouveau projet de type Single View Application et
donnez-lui le nom  pong  1 .
Ce jeu va utiliser plusieurs lments graphiques :
 une image d'arrire-plan de 320 x 480 pixels ;
 une image PNG d'une brique de 70 x 15 pixels ;
 une image PNG d'une raquette de 70 x 15 pixels ;
 une image PNG d'une balle de 16 x 16 pixels.
L'arrire-plan est une quelconque image enregistre au format JPG ou PNG et de
dimensions bien prcises : 320 x 480 pixels. Les briques, la raquette et la balle sont au
format PNG. Vous pouvez crer vous-mmes vos images, mais au cas o, vous pouvez
tlcharger celles que j'ai utilises dans ce chapitre.


Tlcharger
les
images
B
Code web : 233945


1. C'est moins long que  casse-briques  mais tout aussi parlant pour notre application.

388

DFINITION DE L'INTERFACE

Pour accder facilement ces lments graphiques, vous allez les placer dans les ressources de l'application. Cliquez du bouton droit sur la premire icne du volet de
navigation et slectionnez New group dans le menu contextuel. Renommez le nouveau dossier  Resources . Maintenez le bouton gauche de la souris enfonc et glissezdposez les chiers background.png, brique.png, raquette.png et balle.png depuis le Finder dans le dossier Resources de l'application. Au relchement du bouton
gauche de la souris, une bote de dialogue est ache. Assurez-vous que la case Copy
items into destination group's folder (if needed) est coche, puis cliquez sur
Finish. Votre arborescence devrait ressembler la gure 21.2.

Figure 21.2  L'arborescence de votre application devrait ressembler celle-ci

Vous allez maintenant crer l'interface du jeu avec Interface Builder.


Cliquez sur MainStoryboard.storyboard dans le volet de navigation et achez si
ncessaire le volet des utilitaires en cliquant sur l'icne Hide or Show the Utilities
dans la barre d'outils. Vous allez maintenant dposer neuf contrles UIImageView (oui,
vous avez bien lu !) depuis la bibliothque d'objets sur la vue de l'application.
quoi vont servir tous ces objets ? Est-ce qu'ils sont vraiment tous ncessaires ?

Eh bien oui, tous ces objets sont ncessaires : sept vont reprsenter les briques, un la
raquette et le dernier la balle.
Je vais vous montrer comment procder pour un de ces objets, une brique en l'occurrence. En utilisant la mme technique, vous n'aurez aucun mal dnir et positionner
les autres objets. Pour ajouter une brique, suivez les tapes ci-aprs.
1. Glissez-dposez un contrle UIImageView sur la feuille de l'application.
2. Cliquez sur l'icne Show the Attributes inspector dans le volet des utilitaires.
Droulez la liste Image et choisissez  brique.png .
3. Cliquez sur l'icne Show the Size inspector et modiez les dimensions de la
brique :  70  dans la case Width et  15  dans la case Height (c'est la taille de
389

CHAPITRE 21.

UN JEU DE CASSE-BRIQUES

notre brique), comme indiqu la gure 21.3.


4. Dplacez la brique dans la partie suprieure de la vue.

Figure 21.3  Modiez la taille de la brique

Ajoutez puis dplacez les huit objets restant pour obtenir quelque chose ressemblant
la gure 21.4.

Figure 21.4  Disposez les briques comme ceci


Dans votre code, n'oubliez pas de donner aux images les dimensions adquates : 70 x 15 pixels pour la raquette et les briques et 16 x 16 pixels pour
la balle.

390

DFINITION DE L'INTERFACE

Pour en terminer avec l'interface de l'application, vous allez ajouter un contrle Label.
Ce contrle sera utilis pour acher des informations textuelles du type  3, 2, 1,
partez. . .  lorsque le joueur perdra la balle.
Glissez-dposez un contrle Label de la bibliothque d'objets sur la vue. Redimensionnez ce contrle pour qu'il occupe les trois quarts de la vue. Dans l'inspecteur des
attributs, supprimez le contenu de la case Text pour que le Label n'ache rien par
dfaut et choisissez une police System de 50 points, comme la gure 21.5.

Figure 21.5  Placez et paramtrez un Label

Liaison des contrles au code


Pour pouvoir interagir avec ces contrles, vous devez crer des outlets. Contrle-glissezdposez tour tour chacun des objets de la vue sur le chier d'en-ttes et crez les
outlets brique1 brique7, balle, raquette et stop3s (pour le contrle Label). Une
fois tous les outlets crs, le chier d'en-ttes devrait ressembler ceci :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
@property
@property
@property
@property
@property
@property
@property
@property
@property
@property
@end

( weak ,
( weak ,
( weak ,
( weak ,
( weak ,
( weak ,
( weak ,
( weak ,
( weak ,
( weak ,

nonatomic )
nonatomic )
nonatomic )
nonatomic )
nonatomic )
nonatomic )
nonatomic )
nonatomic )
nonatomic )
nonatomic )

IBOutlet
IBOutlet
IBOutlet
IBOutlet
IBOutlet
IBOutlet
IBOutlet
IBOutlet
IBOutlet
IBOutlet

UIImageView * brique1 ;
UIImageView * brique2 ;
UIImageView * brique3 ;
UIImageView * brique4 ;
UIImageView * brique5 ;
UIImageView * brique6 ;
UIImageView * brique7 ;
UILabel * stop3s ;
UIImageView * balle ;
UIImageView * raquette ;

391

CHAPITRE 21.

UN JEU DE CASSE-BRIQUES

Immersion dans le code


Dnition de l'arrire-plan de l'application
Vous allez maintenant commencer crire le code de l'application. La premire tape va
consister dnir l'image d'arrire-plan. Cliquez sur ViewController.m dans le volet
de navigation et insrez l'instruction suivante au dbut de la mthode viewDidLoad :
1

self . view . backgroundColor = [[ UIColor alloc ]


initWithPatternImage :[ UIImage imageNamed : @" background . png "
]];

Cette instruction a dj t rencontre plusieurs reprises. Elle aecte une image


d'arrire-plan (mthode backgroundColor) la vue courante (self.view) en utilisant
une image dans les ressources ([[UIColor alloc] initWithPatternImage:[UIImage
imageNamed:). L'image utilise a pour nom  background.png . Libre vous d'utiliser
une quelconque autre image, pourvu que sa taille soit gale 320 x 480 pixels.
Vous pouvez lancer l'application. Vous l'avez bien mrit. La gure 21.6 reprsente ce
que vous devriez obtenir.

Figure 21.6  Les images de l'application s'achent correctement


N'essayez pas de jouer : nous n'avons pas encore crit le code pour a.

392

IMMERSION DANS LE CODE

Dplacement de la balle
Avant de pouvoir jouer, plusieurs tapes sont ncessaires. Dans un premier temps,
vous allez donner vie la balle. Pour cela, vous allez devoir mettre en place un timer. Mais avant, retournez dans le chier d'en-ttes et dnissez la variable d'instance
vitesseBalle comme suit :
1
2
3
4

@interface ViewController : UIViewController


{
CGPoint vitesseBalle ;
}

La variable vitesseBalle est une structure CGPoint. Elle consiste en deux ottants
qui dnissent des coordonnes. Dans notre cas, nous utiliserons cette variable pour
calculer l'endroit o la balle doit tre ache. La gure 21.7 vous montre ce que dit la
documentation Apple sur la structure CGPoint.

Figure 21.7  La documentation Apple concernant CGPoint

Retournez dans le chier ViewController.m et dnissez la mthode boucleJeu comme


suit :
1
2

-( void ) boucleJeu
{

393

CHAPITRE 21.

3
4
5
6
7
8

UN JEU DE CASSE-BRIQUES

balle . center = CGPointMake ( balle . center . x + vitesseBalle . x ,


balle . center .y + vitesseBalle .y ) ;
if ( balle . center . x > self . view . bounds . size . width || balle .
center . x < 0 )
vitesseBalle . x = - vitesseBalle . x ;
if ( balle . center . y > self . view . bounds . size . height || balle .
center . y < 0 )
vitesseBalle . y = - vitesseBalle . y ;

Examinons les instructions utilises dans cette mthode.


La ligne 3 calcule les prochaines coordonnes de la balle (balle.center). Ces coordonnes sont obtenues en ajoutant aux coordonnes actuelles (balle.center.x et
balle.center.y) le dplacement dsir (vitesseBalle.x et vitesseBalle.y). Tout
ce petit monde est pass une instruction CGPointMake, qui retourne les nouvelles
coordonnes de la balle (CHPointMake(...)). Pour que la balle se dplace, il sut
d'aecter le rsultat de l'instruction CGPointMake la proprit center de l'objet
balle, c'est--dire au centre de la balle :
balle . center = CGPointMake ( balle . center . x + vitesseBalle . x ,
balle . center .y + vitesseBalle .y ) ;

L'instruction suivante s'intresse l'abscisse (la position horizontale) de la balle qui,


rappelons-le, vient d'tre calcule. Si cette abscisse est suprieure la largeur de la
vue (balle.center.x > self.view.bounds.size.width) ou si elle est ngative (||
balle.center.x < 0), il sut d'inverser la direction en X de la balle pour qu'elle ne
sorte pas de la vue (vitesseBalle.x = -vitesseBalle.x;). Ce qui donne :
1
2

if ( balle . center . x > self . view . bounds . size . width || balle .


center . x < 0 )
vitesseBalle . x = - vitesseBalle . x ;

Examinez l'instruction suivante. Je suis sr que vous y voyez quelques similitudes :


1
2

if ( balle . center . y > self . view . bounds . size . height || balle .


center . y < 0 )
vitesseBalle . y = - vitesseBalle . y ;

Ici, c'est l'ordonne (la position verticale) qui est examine. Si elle dpasse la hauteur de
la vue (balle.center.y > self.view.bounds.size.height) ou si elle est ngative
(|| balle.center.y < 0), la direction en Y est inverse pour que la balle ne sorte
pas de la vue (vitesseBalle.y = -vitesseBalle.y).
Tout cela est bien joli, mais dans quel sens va partir la balle ? Je crois bien
que la direction de la balle n'a pas t dnie au lancement de l'application.

Eectivement. Nous allons immdiatement rparer cette lacune en ajoutant l'instruction suivante dans la mthode viewDidLoad :
394

IMMERSION DANS LE CODE

vitesseBalle = CGPointMake ( 10 , 15 ) ;

Cette instruction dnit l'objet CGPoint vitesseBalle et aecte les valeurs 10 et 15


ses composantes X et Y. Par la suite, nous utiliserons cet objet pour modier les
coordonnes de la balle. . . et donc la dplacer.
Je vous sens impatients de lancer l'application pour voir la balle se dplacer dans la
vue. Je ne vais pas vous priver de ce plaisir. Cliquez sur Run et admirez. . . admirez. . .
cette belle balle immobile au milieu de la vue !
Que se passe-t-il ? J'ai pourtant respect la lettre tout ce qui a t dit
jusqu'ici !

Rchissez un peu. Vous avez dni une mthode pour animer la balle, mais croyezvous que cette mthode va s'excuter toute seule ? Bien sr que non, il faut le lui
demander en mettant en place un timer. Ajoutez l'instruction suivante dans la mthode
viewDidLoad :
1

timer1 = [ NSTimer scheduledTimerWithTimeInterval : 0 . 05 target :


self selector : @selector ( boucleJeu ) userInfo : nil repeats : YES
];

Cette instruction dnit l'objet timer1 (timer1 =) en utilisant un message ObjectiveC. Le message dit en substance ceci :
 le code du timer doit tre excut toutes les 0,05 seconde, soit 20 fois par seconde :
[NSTimer scheduledTimerWithTimeInterval:0.05 ;
 la mthode excuter se trouve dans la classe courante, c'est--dire celle du contrleur de vue : target:self ;
 la mthode excuter a pour nom boucleJeu : selector:@selector(boucleJeu) ;
 aucune information complmentaire n'est passe cette mthode : userInfo:nil ;
 la mthode doit se rpter indniment (ou du moins jusqu' ce qu'il soit dsactiv) :
repeats:YES].
Pensez galement dclarer l'objet timer dans le chier ViewController.h :
1
2
3
4
5

@interface ViewController : UIViewController


{
CGPoint vitesseBalle ;
NSTimer * timer1 ;
}

Maintenant, vous pouvez lancer l'application et voir (oh merveille !) la balle se dplacer
et rebondir sur les coins de l'cran (et votre doigt sur le device).

Dplacement de la raquette
Vous allez maintenant donner vie la raquette et lui demander de suivre la souris dans
le simulateur.
395

CHAPITRE 21.

UN JEU DE CASSE-BRIQUES

Dnissez la mthode suivante dans le chier ViewController.m (par exemple, juste


aprs la mthode boucleJeu) :
1
2
3
4
5
6

-( void ) touchesMoved :( NSSet *) touches withEvent :( UIEvent *)


event
{
UITouch * touch = [[ event allTouches ] anyObject ];
CGPoint location = [ touch locationInView : touch . view ];
raquette . center = CGPointMake ( location .x , raquette . center . y ) ;
}

Examinons les instructions contenues dans cette mthode. la ligne 3, l'objet touch
de classe UITouch est dni (UITouch *touch). Il est initialis avec toutes les actions
toucher de l'utilisateur (= [[event allTouches] anyObject];) :
UITouch * touch = [[ event allTouches ] anyObject ];

La ligne 4 dnit l'objet location de classe CGPoint (CGPoint location) et l'initialise


avec la position du toucher (= [touch locationInView:touch.view];) :
CGPoint location = [ touch locationInView : touch . view ];

La variable location contient la position du doigt de l'utilisateur dans la vue. L'instruction de la ligne 5 aecte l'abscisse de cette position celle de la raquette (raquette.center
= CGPointMake(location.x, ...). L'ordonne de la raquette, quant elle, ne doit pas
suivre le doigt de l'utilisateur, mais rester sur une ligne horizontale (raquette.center.y) :
raquette . center = CGPointMake ( location .x , raquette . center . y ) ;

Lancez l'application en cliquant sur Run. La raquette doit maintenant suivre les mouvements de la souris, bouton gauche enfonc. Quelle russite !
Lisez vite la suite, vous allez dcouvrir comment dtecter des collisions entre deux
objets. Cela vous permettra de faire rebondir la balle sur la raquette et d'eacer les
briques sur lesquelles rebondit la balle.

Dtection des collisions


Comme nous l'avons vu prcdemment, il est possible de connatre les coordonnes
d'un objet en utilisant les proprits center.x et center.y de cet objet. Par exemple,
les coordonnes de la balle sont obtenues avec les expressions balle.center.x et
balle.center.y.
Est-ce que vous savez comment dtecter la collision entre deux objets ? En testant
leurs coordonnes center.x et center.y bien entendu ! Encore plus fort : vous pouvez
utiliser la mthode CGRectIntersectsRect pour tester la collision entre deux objets.
Voyons comment tester le contact de la balle sur la premire brique. Ajoutez le test
suivant dans la mthode boucleJeu :
1

if (( CGRectIntersectsRect ( balle . frame , brique1 . frame ) ) && (


brique1 . hidden == NO ) )

396

IMMERSION DANS LE CODE

2
3
4
5

{
}

brique1 . hidden = YES ;


vitesseBalle . y = - vitesseBalle . y ;

La premire ligne teste la collision (CGRectIntersectsRect) entre la balle (balle.frame)


et la premire brique (brique1.frame), dans le cas o cette brique est toujours ache
(brique1.hidden == NO) :
1

if (( CGRectIntersectsRect ( balle . frame , brique1 . frame ) ) && (


brique1 . hidden == NO ))

La troisime ligne cache la premire brique :


1

brique1 . hidden = YES ;

Quant la quatrime ligne, elle inverse le sens de progression vertical de la balle :


1

vitesseBalle . y = - vitesseBalle . y ;

La brique 1 n'est pas la seule prsente dans la vue. Vous devez donc crire un code
quivalent pour les briques 2 7 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

if (( CGRectIntersectsRect ( balle . frame , brique2 . frame ) )


brique2 . hidden == NO ))
{
brique2 . hidden = YES ;
vitesseBalle . y = - vitesseBalle . y ;
}
if (( CGRectIntersectsRect ( balle . frame , brique3 . frame ) )
brique3 . hidden == NO ))
{
brique3 . hidden = YES ;
vitesseBalle . y = - vitesseBalle . y ;
}
if (( CGRectIntersectsRect ( balle . frame , brique4 . frame ) )
brique4 . hidden == NO ))
{
brique4 . hidden = YES ;
vitesseBalle . y = - vitesseBalle . y ;
}
if (( CGRectIntersectsRect ( balle . frame , brique5 . frame ) )
brique5 . hidden == NO ))
{
brique5 . hidden = YES ;
vitesseBalle . y = - vitesseBalle . y ;
}
if (( CGRectIntersectsRect ( balle . frame , brique6 . frame ) )
brique6 . hidden == NO ))
{
brique6 . hidden = YES ;
vitesseBalle . y = - vitesseBalle . y ;

&& (

&& (

&& (

&& (

&& (

397

CHAPITRE 21.

25
26
27
28
29
30

UN JEU DE CASSE-BRIQUES

}
if (( CGRectIntersectsRect ( balle . frame , brique7 . frame ) )
brique7 . hidden == NO ) )
{
brique7 . hidden = YES ;
vitesseBalle . y = - vitesseBalle . y ;
}

&& (

Si vous voulez crire un code plus condens, vous pouvez remplacer ces sept
blocs if par une boucle. Je n'ai pas choisi cette voie pour ne pas vous embrouiller : il y a dj tant de nouveauts dans ce chapitre !

Excutez l'application. Sous vos yeux bahis, les briques disparaissent les unes aprs
les autres ! Il nous reste encore dtecter la collision entre la balle et la raquette et
ragir en consquence.
Ajoutez le test suivant dans la mthode boucleJeu :
1
2
3
4
5

If ( CGRectIntersectsRect ( balle . frame , raquette . frame ) )


{
if ( balle . center . y < raquette . center . y )
vitesseBalle . y = - vitesseBalle . y ;
}

La ligne 1 teste la collision entre la balle (balle.frame) et la raquette (raquette.frame) :


1

if ( CGRectIntersectsRect ( balle . frame , raquette . frame ) )

La ligne 3 teste si la balle se trouve plus bas que la raquette :


1

if ( balle . center . y < raquette . center . y )

Dans ce cas, il convient d'inverser le sens de progression verticale de la balle pour qu'elle
ne sorte pas de la vue :
1

vitesseBalle . y = - vitesseBalle . y ;

Pour l'instant, nous n'allons pas grer la perte de la balle. Cela se fera un peu
plus loin dans le tutoriel.

Excutez l'application. a y est, la balle rebondit sur la raquette. Bravo ! Il est temps
de passer l'tape suivante.

Musique de fond et bruits vnementiels


Pour ajouter une musique de fond l'application, vous utiliserez la technique tudie
dans la section  Jouer des lments audio  du chapitre consacr au son. Reportezvous cette section pour avoir des renseignements dtaills sur sa mise en uvre (page
322).
398

IMMERSION DANS LE CODE

Une musique de fond, c'est bien, mais ce serait vraiment mieux si la balle produisait
un bruit de balle lorsqu'elle frappe sur la raquette ou sur une brique. Pour cela, vous
allez devoir utiliser un objet SystemSoundID.


Tlcharger le son
B
Code web : 990717


Ajoutez un son au format CAF dans les ressources de l'application. Cliquez sur le
chier ViewController.h dans le volet de navigation et ajoutez l'instruction suivante
dans la dnition de l'interface :
1

SystemSoundID bruit ;

Rendez-vous dans le chier


mthode viewDidLoad :
1

ViewController.m

et ajoutez cette instruction dans la

AudioServicesCreateSystemSoundID ( CFBundleCopyResourceURL (
CFBundleGetMainBundle () , CFSTR ( " pong " ) , CFSTR ( " caf " ) , NULL ) ,
& bruit ) ;

Cette instruction met en relation le chier audio jouer ( pong.caf  dans cet exemple)
et un objet SystemSoundID qui sera utilis pour jouer le son (bruit dans cet exemple).
Maintenant, vous devez encore ajouter quelques instructions pour jouer le son  pong.caf 
lorsque la balle entre en contact avec la raquette ou avec une brique. Reprez le test
de collision entre la balle et la raquette dans la mthode boucleJeu et compltez-le
comme suit :
1
2
3
4
5
6
7
8

if ( CGRectIntersectsRect ( balle . frame , raquette . frame ) )


{
if ( balle . center . y < raquette . center . y )
{
vitesseBalle . y = - vitesseBalle . y ;
AudioServicesPlaySystemSound ( bruit ) ;
}
}

La ligne 6 joue le son  bruit  via la mthode AudioServicesPlaySystemSound.


Vous allez maintenant ajouter la mme instruction dans les tests de collision entre la
balle et chacune des briques. Voici par exemple quoi doit ressembler le test de collision
entre la balle et la brique 1 :
1
2
3
4
5
6

if (( CGRectIntersectsRect ( balle . frame , brique1 . frame ) ) && (


brique1 . hidden == NO ))
{
brique1 . hidden = YES ;
vitesseBalle . y = - vitesseBalle . y ;
AudioServicesPlaySystemSound ( bruit ) ;
}

Insrez cette mme instruction dans les six autres tests de collision.
399

CHAPITRE 21.

UN JEU DE CASSE-BRIQUES

Perte de la balle
Je ne sais pas si vous avez remarqu, mais ce jeu prsente un (petit) dfaut : si le
joueur n'arrive pas rattraper la balle avec la raquette, celle-ci rebondit sur la partie
infrieure de l'cran. Que diriez-vous d'ajouter un traitement relatif la perte de la
balle ? Par exemple. . . mettre un rire pour augmenter le stress du joueur.


Tlcharger
le
son
B
Code web : 718763


Commencez par ajouter un son au format caf dans les ressources de l'application. Pour
que ce son puisse tre jou, vous devez dnir un objet SystemSoundID et le relier ce
son. Ajoutez l'instruction suivante dans la partie interface du chier ViewController.h :
SystemSoundID rire ;

Vous allez maintenant agir sur le code. Cliquez sur ViewController.h dans le volet de navigation et ajoutez l'instruction suivante un peu avant la n de la mthode
viewDidLoad :
AudioServicesCreateSystemSoundID ( CFBundleCopyResourceURL (
CFBundleGetMainBundle () , CFSTR ( " rire ") , CFSTR ( " caf " ) , NULL ) ,
& rire ) ;

Pour savoir si le joueur a laiss passer la balle, ajoutez le test suivant dans la mthode
boucleJeu :
1
2
3
4
5

if ( balle . center . y > self . view . bounds . size . height )


{
AudioServicesPlaySystemSound ( rire ) ;
balle . center = CGPointMake ( 100 . 0f , 100 . 0f ) ;
}

Si l'ordonne de la balle (balle.center.y) est suprieure la hauteur de la vue


(self.view.bounds.size.height), les instructions comprises entre les accolades sont
excutes.
L'instruction de la ligne 3 met un son pour signier la perte de la balle :
1

AudioServicesPlaySystemSound ( rire ) ;

Quant l'instruction de la ligne 4, elle repositionne la balle pour poursuivre la partie :


1

balle . center = CGPointMake ( 100 . 0f , 100 . 0f ) ;

La touche nale
Pour terminer cette application, nous allons acher un message dans le Label lorsque
toutes les briques ont t eaces et mettre n la boucle de jeu. Rendez-vous dans
le chier ViewController.m et ajoutez le bloc d'instructions suivant dans la mthode
boucleJeu :
400

LE CODE DE L'APPLICATION

2
3
4
5

if (( brique1 . hidden == YES ) && ( brique2 . hidden == YES ) && (


brique3 . hidden == YES ) && ( brique4 . hidden == YES ) && (
brique5 . hidden == YES ) && ( brique6 . hidden == YES ) && (
brique7 . hidden == YES ) )
{
stop3s . text = @ " Bravo ! " ;
[ timer1 invalidate ];
}

a y est, l'application est entirement fonctionnelle. Amusez-vous bien !


Si vous testez cette application dans le simulateur iOS 5.0, il se peut que vous
obteniez une erreur rallonge dans la console. Ne vous en faites pas : cette
erreur n'en est pas vraiment une et l'application fonctionne la perfection
sur un iPhone, un iPod Touch ou un iPad sous iOS 5. Un correctif devrait
tre intgr dans les prochaines mises jour de Xcode. Si cette erreur vous
drange vraiment, vous pouvez opter pour une solution alternative accessible
grce au code web suivant.

Voir la solution alternative


Code web : 510881

Le code de l'application
Le code de l'application se trouve dans le dossier pong.


Copier
ce
code
B
Code web : 890053


ViewController.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# import < UIKit / UIKit .h >


# import < AVFoundation / AVFoundation .h >
# import < AudioToolbox / AudioToolbox .h >
@interface ViewController : UIViewController <
AVAudioPlayerDelegate >
{
CGPoint vitesseBalle ;
NSTimer * timer1 ;
AVAudioPlayer * audioPlayer ;
SystemSoundID bruit ;
SystemSoundID rire ;
}
@property ( weak , nonatomic ) IBOutlet UIImageView * brique1 ;
@property ( weak , nonatomic ) IBOutlet UIImageView * brique2 ;

401

CHAPITRE 21.

16
17
18
19
20
21
22
23
24

@property
@property
@property
@property
@property
@property
@property
@property
@end

UN JEU DE CASSE-BRIQUES

( weak ,
( weak ,
( weak ,
( weak ,
( weak ,
( weak ,
( weak ,
( weak ,

nonatomic )
nonatomic )
nonatomic )
nonatomic )
nonatomic )
nonatomic )
nonatomic )
nonatomic )

IBOutlet
IBOutlet
IBOutlet
IBOutlet
IBOutlet
IBOutlet
IBOutlet
IBOutlet

UIImageView * brique3 ;
UIImageView * brique4 ;
UIImageView * brique5 ;
UIImageView * brique6 ;
UIImageView * brique7 ;
UILabel * stop3s ;
UIImageView * balle ;
UIImageView * raquette ;

ViewController.m
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

# import " ViewController . h "


@implementation ViewController
@synthesize brique1 ;
@synthesize brique2 ;
@synthesize brique3 ;
@synthesize brique4 ;
@synthesize brique5 ;
@synthesize brique6 ;
@synthesize brique7 ;
@synthesize stop3s ;
@synthesize balle ;
@synthesize raquette ;
- ( 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 : @" californie . jpg "
]];
vitesseBalle = CGPointMake ( 10 , 15 ) ;
timer1 = [ NSTimer scheduledTimerWithTimeInterval : 0 . 05 target :
self selector : @selector ( boucleJeu ) userInfo : nil repeats :
YES ];
UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback ;
AudioSessionSetProperty ( kAudioSessionProperty_AudioCategory ,
sizeof ( sessionCategory ) , & sessionCategory ) ;
NSData * soundFileData ;
soundFileData = [ NSData dataWithContentsOfURL :[ NSURL
fileURLWithPath :[[ NSBundle mainBundle ] pathForResource : @ "

402

LE CODE DE L'APPLICATION

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

morceau . mp3 " ofType : NULL ]]];


audioPlayer = [[ AVAudioPlayer alloc ] initWithData :
soundFileData error : NULL ];
audioPlayer . delegate = self ;
[ audioPlayer setVolume : 1 . 0 ];
[ audioPlayer play ];
AudioServicesCreateSystemSoundID ( CFBundleCopyResourceURL (
CFBundleGetMainBundle () , CFSTR ( " pong " ) , CFSTR ( " caf " ) , NULL
) , & bruit );
AudioServicesCreateSystemSoundID ( CFBundleCopyResourceURL (
CFBundleGetMainBundle () , CFSTR ( " rire " ) , CFSTR ( " caf " ) , NULL
) , & rire ) ;

-( void ) boucleJeu
{
balle . center = CGPointMake ( balle . center . x + vitesseBalle . x ,
balle . center . y + vitesseBalle . y ) ;
if ( balle . center . x > self . view . bounds . size . width || balle .
center . x < 0 )
vitesseBalle . x = - vitesseBalle . x ;
if ( balle . center . y > self . view . bounds . size . height || balle .
center . y < 0 )
vitesseBalle . y = - vitesseBalle . y ;
if ( CGRectIntersectsRect ( balle . frame , raquette . frame ) )
{
if ( balle . center . y < raquette . center . y )
{
vitesseBalle . y = - vitesseBalle . y ;
AudioServicesPlaySystemSound ( bruit ) ;
}
}
if ( balle . center . y > self . view . bounds . size . height )
{
AudioServicesPlaySystemSound ( rire ) ;
balle . center = CGPointMake ( 100 . 0f , 100 . 0f ) ;
}
if (( CGRectIntersectsRect ( balle . frame , brique1 . frame ) ) && (
brique1 . hidden == NO ))
{
brique1 . hidden = YES ;
vitesseBalle . y = - vitesseBalle . y ;
AudioServicesPlaySystemSound ( bruit ) ;
}
if (( CGRectIntersectsRect ( balle . frame , brique2 . frame ) ) && (
brique2 . hidden == NO ))
{

403

CHAPITRE 21.

brique2 . hidden = YES ;


vitesseBalle . y = - vitesseBalle . y ;
AudioServicesPlaySystemSound ( bruit ) ;

72
73
74
75
76

}
if (( CGRectIntersectsRect ( balle . frame , brique3 . frame ) )
brique3 . hidden == NO ) )
{
brique3 . hidden = YES ;
vitesseBalle . y = - vitesseBalle . y ;
AudioServicesPlaySystemSound ( bruit ) ;
}
if (( CGRectIntersectsRect ( balle . frame , brique4 . frame ) )
brique4 . hidden == NO ) )
{
brique4 . hidden = YES ;
vitesseBalle . y = - vitesseBalle . y ;
AudioServicesPlaySystemSound ( bruit ) ;
}
if (( CGRectIntersectsRect ( balle . frame , brique5 . frame ) )
brique5 . hidden == NO ) )
{
brique5 . hidden = YES ;
vitesseBalle . y = - vitesseBalle . y ;
AudioServicesPlaySystemSound ( bruit ) ;
}
if (( CGRectIntersectsRect ( balle . frame , brique6 . frame ) )
brique6 . hidden == NO ) )
{
brique6 . hidden = YES ;
vitesseBalle . y = - vitesseBalle . y ;
AudioServicesPlaySystemSound ( bruit ) ;
}
if (( CGRectIntersectsRect ( balle . frame , brique7 . frame ) )
brique7 . hidden == NO ) )
{
brique7 . hidden = YES ;
vitesseBalle . y = - vitesseBalle . y ;
AudioServicesPlaySystemSound ( bruit ) ;
}

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

108
109
110
111
112
113

UN JEU DE CASSE-BRIQUES

&& (

&& (

&& (

&& (

&& (

if (( brique1 . hidden == YES ) && ( brique2 . hidden == YES ) && (


brique3 . hidden == YES ) && ( brique4 . hidden == YES ) && (
brique5 . hidden == YES ) && ( brique6 . hidden == YES ) && (
brique7 . hidden == YES ) )
{
stop3s . text = @ " Bravo ! " ;
[ timer1 invalidate ];
}
}

404

LE CODE DE L'APPLICATION

114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161

-( void ) touchesMoved :( NSSet *) touches withEvent :( UIEvent *)


event
{
UITouch * touch = [[ event allTouches ] anyObject ];
CGPoint location = [ touch locationInView : touch . view ];
raquette . center = CGPointMake ( location .x , raquette . center . y ) ;
}
- ( void ) viewDidUnload
{
[ self setBrique1 : nil ];
[ self setBrique2 : nil ];
[ self setBrique3 : nil ];
[ self setBrique4 : nil ];
[ self setBrique5 : nil ];
[ self setBrique6 : nil ];
[ self setBrique7 : nil ];
[ self setStop3s : nil ];
[ self setBalle : nil ];
[ self setRaquette : 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

405

CHAPITRE 21.

162
163
164
165

UN JEU DE CASSE-BRIQUES

return ( interfaceOrientation !=
UIInterfaceOrientationPortraitUpsideDown ) ;

@end

En rsum
 Pour dplacer un objet sur l'cran, vous devez mettre en place un timer et modier
les coordonnes de l'objet dans la mthode active intervalle rgulier par le timer.
 Pour manipuler les coordonnes d'un objet, le plus simple consiste utiliser des objets
CGPoint, qui permettent de stocker deux valeurs ottantes (ici, les coordonnes X
et Y de l'objet).
 Pour contrler les mouvements de toucher, dnissez un objet UITouch, et spciez quelles actions de toucher doivent tre captures. La mthode locationInView,
applique l'objet UITouch, donne les coordonnes X, Y du toucher.
 Pour dtecter la collision entre deux objets sur l'cran, il sut de comparer les
coordonnes X et Y de leurs centres respectifs.

406

Chapitre

22

TP : Capturez les vers


Dicult :

ue diriez-vous d'crire votre propre jeu ? Dans ce TP, je vous propose de mettre
en uvre les techniques tudies dans cette partie (et aussi un peu dans les parties
prcdentes). Le but de votre mission, si vous l'acceptez, va consister radiquer une
colonie de vers qui menace la sant d'un vgtal sur lequel elle a lu domicile.
Je vous sens enthousiastes, mais galement soucieux des dicults venir. . . N'ayez
crainte : si vous suivez les conseils que je vais vous donner, tout se passera merveille.

407

CHAPITRE 22.

TP : CAPTUREZ LES VERS

Principe du TP
Un aperu de ce qui vous attend

Dans ce TP, vous allez devoir :


 acher une image en arrire-plan du device ;
 mettre en place un timer ;
 acher/faire disparatre de petits objets graphiques (aussi appels  sprites ) ;
 tester les ventuelles collisions ;
 ajouter une musique d'arrire-plan ;
 ajouter un bruitage sur les actions du joueur et sur la perte d'un point.
Votre mission va consister acher des sprites sur l'cran pendant une dure alatoire
comprise entre 0,5 et 1,5 seconde, puis les faire disparatre. Si le joueur touche un
sprite avant qu'il ne disparaisse, il gagne un point. Dans le cas contraire, un son est
jou pour lui signier qu'il vient d'chouer.
La gure 22.1 reprsente ce que vous devez obtenir (libre vous de choisir un autre
fond d'cran et un autre sprite) :

Figure 22.1  L'application  Capturez les vers 

408

PRINCIPE DU TP

Les ressources du projet

Le projet utilisera les ressources suivantes :


 une image JPG ou PNG de 320 x 480 pixels pour l'arrire-plan ;
 une image PNG transparente de 60 x 60 pixels pour le sprite ;
 un morceau MP3 pour l'arrire-plan sonore ;
 un son CAF qui sera mis lorsque le joueur pointe un ver avec son doigt ;
 un autre son CAF qui sera mis lors de la disparition d'un ver ou lorsque le joueur
pointe l'arrire-plan et non le ver.
Vous pouvez tlcharger les ressources que j'ai utilises pour vous faciliter la tche,
mais rien ne vous empche de crer les vtres.


Tlcharger
les
ressources
B
Code web : 451253


Mise en place d'un timer

Le timer du jeu de casse-briques est une bonne base de dpart. Mais attention, il ne
s'agit que d'une base de dpart. N'oubliez pas que le sprite devra s'acher pendant
une dure variable comprise entre 0,5 et 1,5 seconde. D'autre part, un message de
dmarrage du type  Attention . . . 3 . . . 2 . . . 1 . . . C'est vous  devra s'acher au
dbut de la partie. Le dlai entre les direntes parties du message sera x 1 seconde,
pour que le joueur ait le temps de lire ce qui est crit. tant donn qu'un seul timer
sera utilis pour rythmer ces direntes phases de jeu, il sera ncessaire de modier
son paramtrage pendant l'excution du jeu.
Achage/disparition d'un sprite

Le sprite sera ach dans un contrle Image View. Pour le faire disparatre/apparatre,
vous utiliserez sa proprit alpha. Aectez la valeur 0.0f cette proprit pour faire
disparatre le ver, et la valeur 1.0f pour le faire apparatre.
Je ne sais pas si vous vous rappelez du chapitre prcdent, dans lequel les
briques taient caches en agissant sur leur proprit hidden. Ici, je vous
propose d'utiliser une variante qui produira le mme eet. N'oubliez pas que
la documentation de Xcode est une allie de choix lorsque vous exprimentez
une nouvelle technique.

Tests de collisions

Il vous sut d'utiliser la mthode touchesBegan pour obtenir les coordonnes du


toucher (une technique similaire, base sur la mthode touchesMoved a dj t tudie
dans le jeu de casse-briques). Comparez les coordonnes du toucher avec celles du sprite
et vous saurez si le joueur a bien vis ou s'il a besoin de nouvelles lunettes !
409

CHAPITRE 22.

TP : CAPTUREZ LES VERS

Je ne reviendrai pas sur les techniques utiliser pour acher une image
en arrire-plan, jouer une musique de fond ou mettre des bruits lors des
actions du joueur. Ces techniques doivent maintenant tre acquises. Dans le
cas contraire, revenez en arrire pour savoir comment les mettre en uvre.

Je crois que je vous ai bien aids et que vous tes n prts raliser votre propre jeu.
Amusez-vous bien !

Solution
Que votre application fonctionne la perfection ou que vous ayez but sur un ou
plusieurs points de dtail, je vais vous montrer ma faon de voir les choses.
Comme toujours en programmation, il n'y a pas une, mais plusieurs solutions.
C'est pourquoi je parle de  ma faon de voir les choses . Il se peut donc
que vous ayez crit un tout autre code pour parvenir au mme rsultat.

Comme je vous l'ai suggr dans la section  Principe du TP , le projet a t scind en


plusieurs tapes conscutives. Nous allons maintenant examiner chacune de ces tapes.

Cration du projet
Dnissez un nouveau projet de type Single View Application et donnez-lui le nom
 ver . Munissez-vous des ressources suivantes :
 une image JPG ou PNG de 320 x 480 pixels pour l'arrire-plan ;
 une image PNG transparente de 60 x 60 pixels pour le sprite ;
 un morceau MP3 pour l'arrire-plan sonore ;
 un son CAF qui sera mis lorsque le joueur pointe un ver avec son doigt ;
 un autre son CAF qui sera mis lors de la disparition d'un ver ou lorsque le joueur
pointe l'arrire-plan et non le ver.
Pour stocker ces chiers dans l'application, vous allez crer le dossier Resources. Cliquez du bouton droit sur le dossier ver dans le volet de navigation et slectionnez New
Group dans le menu. Donnez le nom  Resources  ce dossier et dplacez les cinq
chiers de ressource depuis le Finder dans le dossier Resources de l'application. La
gure 22.2 reprsente le volet de navigation que vous devriez avoir.
Ici, fondver.jpg est l'image d'arrire-plan du jeu, ver.png le sprite, morceau.mp3 la
musique d'arrire-plan, pong.caf le bruit mis lorsque le joueur appuie sur un sprite
et rire.caf le bruit qui est mis lorsqu'un sprite disparat sans que le joueur ait cliqu
dessus.
410

SOLUTION

Figure 22.2  Les ressources apparaissent dans l'arborescence du projet


Comme vous pouvez le voir, le sprite est un chier PNG. Ce format n'a pas
t choisi au hasard. En eet, les images PNG peuvent contenir des pixels
transparents, ainsi le sprite se superposera parfaitement sur l'image d'arrireplan (gure 22.3). Vous pouvez utiliser une application graphique quelconque
pour crer des images PNG pixels transparents. Par exemple PaintBrush ou
Gimp.

Figure 22.3  gauche, le sprite contient des pixels transparents ; droite, non

Dnition de l'cran de jeu


L'cran de jeu est vraiment simple, il contiendra deux contrles :
 un Image View, pour acher le ver ;
 un Label pour acher le score.
411

CHAPITRE 22.

TP : CAPTUREZ LES VERS

Cliquez sur MainStoryboard.storyboard dans le volet de navigation et ajoutez un


contrle UIImageView ainsi qu'un contrle Label au canevas. Dnissez l'outlet leVer
pour l'Image View et l'outlet leMessage pour le Label.
Le chier d'en-ttes doit maintenant ressembler ceci :
1
2
3
4
5
6
7

# import < UIKit / UIKit .h >


@interface ViewController : UIViewController
@property ( weak , nonatomic ) IBOutlet UIImageView * leVer ;
@property ( weak , nonatomic ) IBOutlet UILabel * leMessage ;
@end

Achage d'une image en arrire-plan


Cliquez sur ViewController.m dans le volet de navigation et insrez la ligne suivante
dans la mthode viewDidLoad ;
1

self . view . backgroundColor = [[ UIColor alloc ]


initWithPatternImage :[ UIImage imageNamed : @" fondver . jpg " ]];

Cette technique a t utilise et explique maintes reprises dans les chapitres prcdents, nous n'y reviendrons pas.

Mise en place du timer


Commencez par dnir la variable d'instance timer1 de classe NSTimer dans le chier
d'en-ttes :
1
2
3
4

interface ViewController : UIViewController <


AVAudioPlayerDelegate >
{
NSTimer * timer1 ;
}

Puis insrez la ligne suivante dans la mthode ViewDidLoad :


1

timer1 = [ NSTimer scheduledTimerWithTimeInterval : 1 . 0f target :


self selector : @selector ( boucleJeu ) userInfo : nil repeats : YES
];

scheduledTimerWithTimeInterval:1.0f met en place un timer excut toutes les secondes. La mthode appele a pour nom BoucleJeu (selector:@selector(boucleJeu)).
Elle se rpte indniment, jusqu' ce que l'application soit arrte par le joueur
(repeats:YES).
Vous vous doutez certainement de ce que sera l'tape suivante : la dnition de la
mthode boucleJeu.
J'ai distingu trois tapes de jeu :

412

SOLUTION

 une tape initiale, pendant laquelle un message indique au joueur que la partie va
commencer ;
 une deuxime tape pendant laquelle le sprite est ach sur l'cran ;
 une troisime tape pendant laquelle le sprite est dissimul.
Pour dnir ces trois tapes, j'ai choisi d'utiliser une variable d'instance de classe int
que j'ai appele etat. Cette variable est dnie dans le chier d'en-ttes :
1
2
3
4
5

@interface ViewController : UIViewController <


AVAudioPlayerDelegate >
{
NSTimer * timer1 ;
int etat ;
// Etat du jeu
}

Voici la structure de la mthode boucleJeu :


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

-( void ) boucleJeu
{
switch ( etat )
{
case 0 :
// D compte de d part
break ;
case 1 :
// Affichage du ver
break ;
case 2 :
// Disparition du ver
break ;
}
}

Il ne reste plus qu' insrer des instructions la suite des trois case pour donner vie
la boucle de jeu
Case 0

Au lancement de l'application, le jeu doit acher un dcompte. L'tape initiale correspond donc etat = 0. Dnissez cette valeur dans la mthode viewDidLoad :
1
2
3
4
5
6

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
etat = 0 ;
timer1 = [ NSTimer scheduledTimerWithTimeInterval : 1 . 0f target :
self selector : @selector ( boucleJeu ) userInfo : nil repeats :
YES ];
}

413

CHAPITRE 22.

TP : CAPTUREZ LES VERS

Au dbut de la partie, un message du type  Attention . . . 3 . . . 2 . . . 1 . . . C'est


vous  doit s'acher dans le Label. Chacune des parties de ce message, c'est--dire
 Attention ,  3 ,  2 ,  1  et  C'est vous  est ache pendant une seconde.
Pour savoir o l'on se trouve dans le dcompte, vous allez dnir la variable d'instance
compteur de classe int dans le chier d'en-ttes :
1
2
3
4
5
6

@interface ViewController : UIViewController


{
NSTimer * timer1 ;
int etat ;
// tat du jeu
int compteur ;
// Compteur de d part de jeu
}

Puis vous allez initialiser cette variable 4 dans la mthode viewDidLoad :


1
2
3
4
5
6
7

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
etat = 0 ;
compteur = 4;
// Compteur au d part du jeu
timer1 = [ NSTimer scheduledTimerWithTimeInterval : 1 . 0f target :
self selector : @selector ( boucleJeu ) userInfo : nil repeats :
YES ];
}

Maintenant, vous allez complter la mthode


dans le Label :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

boucleJeu

pour acher les messages

-( void ) boucleJeu
{
switch ( etat )
{
case 2 :
// Disparition du ver
break ;

414

case 1 :
// Affichage du ver
break ;
case 0 :
// D compte de d part
if ( compteur == 4)
{
[ leMessage setText : @ " Attention " ];
compteur - -;
}
else if (( compteur >= 1 ) && ( compteur <= 3 ) )
{
leMessage . text = [ NSString stringWithFormat : @ "% i ... " ,
compteur ];

SOLUTION

23
24
25
26
27
28
29
30
31
32
33

compteur - -;
}
else if ( compteur == 0 )
{
[ leMessage setText : @ " C ' est vous ! " ];
compteur = 4 ;
etat = 1 ; // Affichage d 'un ver
}
break ;

Examinons ces instructions. Au lancement du jeu, compteur vaut 4. Le test if


== 4) tant vri, les instructions excutes sont donc les suivantes :
1
2
3
4
5

(compteur

if ( compteur == 4 )
{
[ leMessage setText : @ " Attention " ];
compteur - -;
}

L'instruction de la ligne 3 ache le message  Attention  dans le Label et l'instruction


de la ligne 4 dcrmente la variable compteur. La mthode boucleJeu se termine. Elle
sera nouveau excute dans une seconde puisque le timer mis en place a une priode
de 1 seconde.
la deuxime excution de la mthode boucleJeu, compteur vaut 3. C'est donc cette
portion du code qui est excute :
1
2
3
4
5

else if (( compteur >= 1 ) && ( compteur <= 3 ) )


{
leMessage . text = [ NSString stringWithFormat : @ " %i ... " ,
compteur ];
compteur - -;
}

L'instruction de la ligne 3 ache la valeur du compteur dans le Label : 3. La proprit


text du Label tant de type NSString, il est ncessaire d'eectuer une conversion int
-> NSString. C'est la raison d'tre du message de la ligne 3.

La ligne 4 dcrmente la variable compteur qui vaudra 2 lors du prochain passage dans
la mthode boucleJeu.
Vous l'aurez compris, la mme portion de code est excute lorsque compteur vaut 2,
puis vaut 1. Une fois les messages  2  puis  1  achs dans le Label, compteur
vaut 0. C'est donc la dernire partie du code qui est excute :
1
2
3
4
5
6

else if ( compteur == 0 )
{
[ leMessage setText : @ " C ' est vous ! " ];
compteur = 4 ;
etat = 1 ; // Affichage d ' un ver
}

415

CHAPITRE 22.

TP : CAPTUREZ LES VERS

Dans ce cas, la ligne 3 ache  C'est vous  dans le Label, la ligne 4 initialise le
compteur 4 et la ligne 5 aecte la valeur 1 la variable etat, ce qui signie que
la portion de code qui suit le case 1 sera excute lors du prochain passage dans la
mthode boucleJeu.
Case 1

Lorsque etat vaut 1, l'application doit acher un ver sur l'cran pendant une dure
alatoire comprise entre 1 et 3 secondes. Pour accomplir cette tape, vous aurez besoin
de nouvelles variables. Compltez le chier d'en-ttes comme suit :
1
2
3
4
5
6
7
8
9
10
11

@interface ViewController : UIViewController


{
NSTimer * timer1 ;
int etat ;
// tat du jeu
int compteur ;
// Compteur de d part de jeu
float leTemps ; // Dur e de l ' tat actuel
int largeur ;
// Largeur de l ' cran
int hauteur ;
// Hauteur de l ' cran
float posX ;
// Position en X du ver
float posY ;
// Position en Y du ver
}

La variable leTemps sera utilise pour stocker la dure de l'achage du sprite.


Les variables largeur et hauteur contiendront la largeur et la hauteur en pixels du
device. Ces valeurs sont importantes, car tous les devices n'ont pas la mme dnition.
Enn, les variables posX et posY seront utilises pour mmoriser la position du sprite
sur l'cran.
Compltez le code situ entre les instructions case 1: et break; comme suit :
1
2
3
4
5
6
7
8
9
10
11

case 1 :
// Affichage du ver
posX = ( arc4random () % ( largeur - 60 ) ) + 30 ;
posY = ( arc4random () % ( hauteur - 60 ) ) + 30 ;
leVer . center = CGPointMake ( posX , posY ) ;
leVer . alpha = 1 . 0f ;
leTemps = ( arc4random () % 3 ) + 1 ; // Nombre al atoire entre 1
et 3
[ timer1 invalidate ];
timer1 = [ NSTimer scheduledTimerWithTimeInterval : leTemps
target : self selector : @selector ( boucleJeu ) userInfo : nil
repeats : YES ];
etat = 2 ;
break ;

La ligne 3 calcule la position en X du sprite. Pour cela, nous utilisons la fonction


Objective-C arc4random, qui renvoie un nombre entier compris entre 0 et 4 294 967
295. La valeur renvoye tant bien suprieure la taille des crans des iPhones (tant
horizontalement que verticalement), il est ncessaire de la rduire.
416

SOLUTION

La variable largeur reprsente la largeur en pixels de l'cran. tant donn que le


sprite est un carr de 60 x 60 pixels et que la fonction qui l'ache sur l'cran se base
sur son centre, il est ncessaire de restreindre les nombres tirs alatoirement entre 30
et largeur - 30. La premire partie du calcul (arc4random() % (largeur - 60))
renvoie un nombre compris entre 0 et largeur - 60. En lui ajoutant la valeur 30, on
obtient la plage souhaite : 30 largeur - 30.
La ligne 4 utilise un calcul similaire pour obtenir un nombre alatoire compris entre 30
et hauteur - 30 :
1

posY = ( arc4random () % ( hauteur - 60 ) ) + 30 ;

La ligne 5 ache le ver sur l'cran aux coordonnes posX, posY calcules prcdemment :
1

leVer . center = CGPointMake ( posX , posY ) ;

La ligne 6 aecte la valeur 1.0f la proprit alpha du sprite pour le faire apparatre
sur l'cran :
1

leVer . alpha = 1 . 0f ;

La ligne 7 mmorise dans la variable leTemps un nombre entier alatoire compris entre
et 3. Ce nombre va correspondre au temps d'achage du sprite. Libre vous de le
modier comme bon vous semble.
1
1

leTemps = ( arc4random () % 3 ) + 1 ;

La ligne 8 dsactive le timer actuel :


1

[ timer1 invalidate ];

Quant la ligne 9, elle dnit le nouveau timer bas sur la dure alatoire calcule
ligne 7 :
1

timer1 = [ NSTimer scheduledTimerWithTimeInterval : leTemps target


: self selector : @selector ( boucleJeu ) userInfo : nil repeats : YES
];

Enn, la ligne 10 indique que le jeu a chang d'tat. Lors de la prochaine excution
de la mthode boucleJeu, ce sont les instructions qui suivent le case 2: qui seront
excutes :
1

etat = 2 ;

Ah oui, j'allais oublier. Les variables largeur et hauteur n'ont pas t initialises.
Ajoutez les deux lignes suivantes dans la mthode viewDidLoad pour rparer cette
lacune :
1
2

largeur = self . view . bounds . size . width ; // Largeur de l ' cran


hauteur = self . view . bounds . size . height ; // Hauteur de l ' cran

417

CHAPITRE 22.

TP : CAPTUREZ LES VERS

Case 2

Lorsque etat vaut 2, l'application doit faire disparatre le ver qui est ach. La dure
de la disparition (c'est--dire le temps pendant lequel aucun ver n'est ach sur l'cran)
est trs brve : 1/2 seconde. L'application doit galement tester si le joueur a touch le
ver avant qu'il ne disparaisse et, dans le cas contraire, mettre un son. Pour accomplir
cette tape, vous aurez besoin d'une nouvelle variable pour savoir si l'cran a t touch
par le joueur. J'ai choisi d'appeler cette variable aTouche. Dnissez-la dans le chier
d'en-ttes. Tant que vous y tes, dnissez les variables reussi et rate pour tenir le
compte des vers capturs et des vers rats :
1
2
3

int aTouche ;
int reussi ;
int rate ;

// 1 si le joueur a touch l ' cran , 0 sinon


// Nombre de vers captur s
// Nombre de vers rat s

Ces trois variables tant dnies, retournez dans le code et compltez les instructions
entre case 2: et break; comme suit :
1
2
3
4
5
6
7
8
9
10
11
12
13

case 2 :
// Disparition du ver
if ( aTouche == 0 )
{
rate ++; // Sinon , le joueur n 'a pas eu le temps de toucher
l ' cran , donc le ver est rat
leMessage . text = [ NSString stringWithFormat : @ " Vers attrap
s % i rat s % i " , reussi , rate ];
AudioServicesPlaySystemSound ( rire ) ;
}
leVer . alpha = 0 . 0f ;
leTemps = 0 . 5f ;
[ timer1 invalidate ];
timer1 = [ NSTimer scheduledTimerWithTimeInterval : leTemps
target : self selector : @selector ( boucleJeu ) userInfo : nil
repeats : YES ];
etat = 1 ;
break ;

14
15

Examinons ces instructions. Par convention, aTouche vaut 0 si l'cran n'a pas t
touch par le joueur. Il vaut 1 dans le cas contraire. La ligne 3 teste si l'cran n'a pas
t touch. Dans ce cas, cela signie que le joueur n'a pas eu le temps de capturer le
ver. Le nombre de vers rats est donc incrment de 1 :
1

rate ++;

Puis le Label est mis jour en consquence :


1

leMessage . text = [ NSString stringWithFormat : @ " Vers attrap s % i


rat s % i " , reussi , rate ];

Et enn, un son est mis :


418

SOLUTION

AudioServicesPlaySystemSound ( rire ) ;

La ligne 10 fait disparatre le ver de l'cran :


1

leVer . alpha = 0 . 0f ;

La ligne 11 xe le temps de la disparition 1/2 seconde :


1

leTemps = 0 . 5f ;

Rappelez-vous, le ver doit disparatre pendant 1/2 seconde. C'est la raison pour laquelle
la ligne 12 dsactive le timer actuel et la ligne 13 le remplace par un nouveau, bas sur
une priode de 1/2 seconde :
1
2

[ timer1 invalidate ];
timer1 = [ NSTimer scheduledTimerWithTimeInterval : leTemps target
: self selector : @selector ( boucleJeu ) userInfo : nil repeats : YES
];

Enn, la ligne 14 fait passer le jeu dans l'tape 1. La prochaine excution de la mthode
boucleJeu provoquera donc l'achage d'un nouveau sprite :
1

etat = 1 ;

J'espre que vous n'avez pas trop souert en dcortiquant la mthode boucleJeu. Il
faut bien avouer qu'elle tait un peu longue. Mais vous serez certainement d'accord
avec moi, ces instructions n'avaient rien d'insurmontable.
Pour souer un peu, n'hsitez pas lancer l'application. Vous verrez, elle fonctionne
la perfection en ce qui concerne la squence de dpart ainsi que l'achage et la
disparition des sprites.
J'ai une bonne nouvelle pour vous : cette mthode tait de loin la plus complexe de
l'application.

Tests de collisions
Vous allez maintenant crire un peu de code pour tester si la position pointe par
le joueur correspond celle du sprite. Pour cela, il vous sut d'utiliser la mthode
touchesBegan pour obtenir les coordonnes du toucher. Comparez ces coordonnes
avec celles du sprite et vous saurez si le joueur a bien ou mal vis.
Voici le code mettre en place :
1
2
3
4
5
6

-( void ) touchesBegan :( NSSet *) touches withEvent :( UIEvent *)


event
{
aTouche = 1 ; // Le joueur a touch l ' cran
UITouch * touch = [[ event allTouches ] anyObject ];
CGPoint location = [ touch locationInView : touch . view ];
if (( abs ( location . x - posX ) < 30 ) && ( abs ( location . y - posY ) < 30
))

419

CHAPITRE 22.

7
8
9
10
11
12
13
14
15
16

reussi ++;
AudioServicesPlaySystemSound ( bruit ) ;

}
else
{
AudioServicesPlaySystemSound ( rire ) ;
rate ++;
}
leMessage . text = [ NSString stringWithFormat : @ " Vers attrap s
% i rat s % i " , reussi , rate ];

17
18
19
20
21
22

TP : CAPTUREZ LES VERS

// Affichage d ' un autre ver


[ timer1 invalidate ];
timer1 = [ NSTimer scheduledTimerWithTimeInterval : 0 . 0f target :
self selector : @selector ( boucleJeu ) userInfo : nil repeats :
YES ];
etat = 2 ;

la ligne 3, la variable aTouche est initialise 1 pour indiquer que le joueur a touch
l'cran.
Les lignes 4 et 5 rcuprent les coordonnes du toucher. La technique utilise ici a t
dcrite dans la section  Immersion dans le code  du jeu de casse-briques. Reportezvous-y si ncessaire.
La ligne 6 teste si le joueur a touch un sprite. Les entits location.x et location.y
reprsentent les coordonnes du toucher. Quant posX et posY, elles reprsentent le
centre du sprite.
Si :
1. la dirence entre l'abscisse du toucher et l'abscisse du centre du sprite est infrieure 30 ((abs(location.x - posX)<30)) ;
2. la dirence entre l'ordonne du toucher et l'ordonne du centre du sprite est
infrieure 30 ((abs(location.y - post)<30)) ;
cela signie que le joueur a touch le sprite. Dans ce cas, le nombre de vers capturs
est incrment de 1 (ligne 8) et un bruit de capture est mis (ligne 9).
Si le joueur a touch l'cran en dehors du sprite, un rire est mis (ligne 13) et le nombre
de vers rats est incrment de 1 (ligne 14).
Pour terminer, le timer actuel est dsactiv (ligne 19), un nouveau timer eet immdiat (scheduledTimerWithTimeInterval initialis 0.0f) est dni (ligne 20) et
l'application bascule dans l'tape 2 pour dissimuler le ver ach.
Maintenant, il ne reste plus qu' dnir la  couche sonore  de l'application, c'est--dire
la musique d'arrire-plan et les deux bruitages.
420

SOLUTION

Musique d'arrire-plan
Nous avons dj vu cette technique dans un chapitre prcdent. Elle consiste mettre
en place un objet AVAudioPlayer. Commencez par cliquer sur la premire entre
dans le volet de navigation, basculez sur l'onglet Build Phases, dveloppez l'lment
Link Binary with Libraries et ajoutez les frameworks AVFoundation.framework
et AudioToolbox.framework.
Cliquez sur ViewController.h dans le volet de navigation et faites rfrence aux deux
frameworks avec des instructions #import :
1
2

# import < AVFoundation / AVFoundation .h >


# import < AudioToolbox / AudioToolbox .h >

Toujours dans le chier d'en-ttes, implmentez le protocole AVAudioPlayerDelegate :


1

@interface ViewController : UIViewController <


AVAudioPlayerDelegate >

Enn, dnissez les objets suivants :


 audioPlayer de classe AVAudioPlayer ;
 bruit de classe SystemSoundID ;
 rire de classe SystemSoundID.
1
2
3
4
5
6
7

@interface ViewController : UIViewController <


AVAudioPlayerDelegate >
{
...
AVAudioPlayer * audioPlayer ;
SystemSoundID bruit ;
SystemSoundID rire ;
}

Pour activer la musique de fond et rendre accessibles les deux eets spciaux, ajoutez
les instructions suivantes dans la mthode viewDidLoad :
1
2
3
4
5
6
7
8
9
10

AudioSessionInitialize ( NULL , NULL , NULL , ( __bridge void *) self


);
UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback ;
AudioSessionSetProperty ( kAudioSessionProperty_AudioCategory ,
sizeof ( sessionCategory ) , & sessionCategory ) ;
NSData * soundFileData ;
soundFileData = [ NSData dataWithContentsOfURL :[ NSURL
fileURLWithPath :[[ NSBundle mainBundle ] pathForResource : @ "
morceau . mp3 " ofType : NULL ]]];
audioPlayer = [[ AVAudioPlayer alloc ] initWithData : soundFileData
error : NULL ];
audioPlayer . delegate = self ;
[ audioPlayer setVolume : 1 . 0 ];
[ audioPlayer play ];

421

CHAPITRE 22.

TP : CAPTUREZ LES VERS

AudioServicesCreateSystemSoundID ( CFBundleCopyResourceURL (
CFBundleGetMainBundle () , CFSTR ( " pong ") , CFSTR ( " caf " ) , NULL ) ,
& bruit ) ;
AudioServicesCreateSystemSoundID ( CFBundleCopyResourceURL (
CFBundleGetMainBundle () , CFSTR ( " rire ") , CFSTR ( " caf " ) , NULL ) ,
& rire ) ;

11
12

Copier ce code
B
Code web : 247031


Les lignes 1 9 mettent en place la musique de fond, comme nous l'avons vu dans le
chapitre consacr au son. Les lignes 11 et 12 mettent en place les sons bruit et rire.
Et voil, l'application est entirement oprationnelle. J'espre que vous avez pris autant
de plaisir que moi la dvelopper !
Si vous testez cette application dans le simulateur iOS 5.0, il se peut que vous
obteniez une erreur rallonge dans la console. Ne vous en faites pas : cette
erreur n'en est pas vraiment une et l'application fonctionne la perfection
sur un iPhone, un iPod Touch ou un iPad tournant sous iOS 5. Un correctif
devrait tre intgr dans les prochaines mises jour de Xcode. Si cette erreur
vous drange vraiment, vous pouvez opter pour une solution alternative.

Voir la solution alternative


Code web : 510881


L'application se trouve dans le dossier ver. Voici le code de ses deux principaux chiers.


Tlcharger
le
projet
B
Code web : 357752

ViewController.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# import < UIKit / UIKit .h >


# import < AVFoundation / AVFoundation .h >
# import < AudioToolbox / AudioToolbox .h >
@interface ViewController : UIViewController <
AVAudioPlayerDelegate >
{
NSTimer * timer1 ;
int etat ;
// tat du jeu
int compteur ; // Compteur de d part de jeu
float leTemps ; // Dur e de l ' tat actuel
int largeur ;
// Largeur de l ' cran
int hauteur ;
// Hauteur de l ' cran
float posX ;
// Position en X du ver
float posY ;
// Position en Y du ver
int aTouche ;
// 1 si le joueur a touch l ' cran , 0 sinon
int reussi ;
// Nombre de vers captur s

422

SOLUTION

17
18
19
20
21
22
23
24
25

int rate ;
// Nombre de vers r t s
AVAudioPlayer * audioPlayer ;
SystemSoundID bruit ;
SystemSoundID rire ;

@property ( weak , nonatomic ) IBOutlet UIImageView * leVer ;


@property ( weak , nonatomic ) IBOutlet UILabel * leMessage ;
@end

ViewController.m
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

# import " ViewController . h "


# include < stdlib .h >
@implementation ViewController
@synthesize leVer ;
@synthesize leMessage ;
- ( void ) didReceiveMemoryWarning
{
[ super didReceiveMemoryWarning ];
// Release any cached data , images , etc that aren 't in use .
}
# pragma mark - View lifecycle
-( void ) boucleJeu
{
switch ( etat )
{
case 0 :
// D compte de d part
if ( compteur == 4 )
{
[ leMessage setText : @ " Attention " ];
compteur - -;
}
else if (( compteur >= 1 ) && ( compteur <= 3 ) )
{
leMessage . text = [ NSString stringWithFormat : @ " %i ... " ,
compteur ];
compteur - -;
}
else if ( compteur == 0 )
{
[ leMessage setText : @ " C ' est vous ! " ];
compteur = 4 ;
etat = 1 ; // Affichage d ' un ver
}

423

CHAPITRE 22.

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

TP : CAPTUREZ LES VERS

break ;
case 1 :
// Affichage du ver
posX = ( arc4random () % ( largeur - 60 ) ) + 30 ;
posY = ( arc4random () % ( hauteur - 60 ) ) + 30 ;
leVer . center = CGPointMake ( posX , posY ) ;
leVer . alpha = 1 . 0f ;
leTemps = ( arc4random () % 3 ) + 1 ; // Nombre al atoire
entre 1 et 3
[ timer1 invalidate ];
timer1 = [ NSTimer scheduledTimerWithTimeInterval : leTemps
target : self selector : @selector ( boucleJeu ) userInfo : nil
repeats : YES ];
etat = 2 ;
aTouche = 0 ;
break ;
case 2 :
// Disparition du ver
if ( aTouche == 0 )
{
rate ++; // Sinon , le joueur n 'a pas eu le temps de
toucher l ' cran , donc le ver est rat
leMessage . text = [ NSString stringWithFormat : @ " Vers
attrap s % i rat s % i " , reussi , rate ];
AudioServicesPlaySystemSound ( rire ) ;
}
leVer . alpha = 0 . 0f ;
leTemps = 0 . 5f ;
[ timer1 invalidate ];
timer1 = [ NSTimer scheduledTimerWithTimeInterval : leTemps
target : self selector : @selector ( boucleJeu ) userInfo : nil
repeats : YES ];
etat = 1 ;
break ;

-( void ) touchesBegan :( NSSet *) touches withEvent :( UIEvent *)


event
{
aTouche = 1 ; // Le joueur a touch l ' cran
UITouch * touch = [[ event allTouches ] anyObject ];
CGPoint location = [ touch locationInView : touch . view ];
if (( abs ( location . x - posX ) <30 ) && ( abs ( location . y - posY ) < 30
))
{
reussi ++;
AudioServicesPlaySystemSound ( bruit ) ;
}
else

424

SOLUTION

79
80
81
82
83

}
leMessage . text = [ NSString stringWithFormat : @ " Vers attrap s
% i rat s % i " , reussi , rate ];

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

AudioServicesPlaySystemSound ( rire ) ;
rate ++;

// Affichage d 'un autre ver


[ timer1 invalidate ];
timer1 = [ NSTimer scheduledTimerWithTimeInterval : 0 . 0f target :
self selector : @selector ( boucleJeu ) userInfo : nil repeats :
YES ];
etat = 2 ;

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
// Arri re - plan
self . view . backgroundColor = [[ UIColor alloc ]
initWithPatternImage :[ UIImage imageNamed : @ " fondver . jpg " ]];
// Audio
AudioSessionInitialize ( NULL , NULL , NULL , ( __bridge void *)
self ) ;
UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback ;
AudioSessionSetProperty ( kAudioSessionProperty_AudioCategory ,
sizeof ( sessionCategory ) , & sessionCategory ) ;
NSData * soundFileData ;
soundFileData = [ NSData dataWithContentsOfURL :[ NSURL
fileURLWithPath :[[ NSBundle mainBundle ] pathForResource : @ "
morceau . mp3 " ofType : NULL ]]];
audioPlayer = [[ AVAudioPlayer alloc ] initWithData :
soundFileData error : NULL ];
audioPlayer . delegate = self ;
[ audioPlayer setVolume : 1 . 0 ];
[ audioPlayer play ];
AudioServicesCreateSystemSoundID ( CFBundleCopyResourceURL (
CFBundleGetMainBundle () , CFSTR ( " pong " ) , CFSTR ( " caf " ) , NULL
) , & bruit );
AudioServicesCreateSystemSoundID ( CFBundleCopyResourceURL (
CFBundleGetMainBundle () , CFSTR ( " rire " ) , CFSTR ( " caf " ) , NULL
) , & rire ) ;
// Timer
etat = 0 ;
reussi = 0 ;
rate = 0 ;

// tat 0 au d part du jeu : message de d part


// Aucun ver captur au d part
// Aucun ver rat au d part

425

CHAPITRE 22.

116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

TP : CAPTUREZ LES VERS

compteur = 4; // Compteur au d part du jeu


largeur = self . view . bounds . size . width ; // Largeur de l ' cran
hauteur = self . view . bounds . size . height ; // Hauteur de l ' cran
timer1 = [ NSTimer scheduledTimerWithTimeInterval : 1 . 0f target :
self selector : @selector ( boucleJeu ) userInfo : nil repeats :
YES ];

- ( void ) viewDidUnload
{
[ self setLeVer : nil ];
[ self setLeMessage : nil ];
[ self setLeVer : 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

426

Cinquime partie
Tester et publier ses applications

427

Chapitre

23

Gestion des matriels et des identits


numriques
Dicult :

e chapitre ne s'intresse pas la publication des applications ; c'est encore trop tt.
Par contre, vous y apprendrez tester vos applications, dans le simulateur 1 et sur
device. Vous verrez galement comment mettre jour la version du systme iOS sur
un device et comment eectuer des captures d'cran.
Tous ces points sont autant d'tapes ncessaires avant la publication.
Mais assez palabr, commenons sans plus attendre !

1. Ce chapitre revient sur des choses dj vues prcdemment ; c'est une piqre de rappel.

429

CHAPITRE 23.

GESTION DES MATRIELS ET DES IDENTITS

NUMRIQUES

Dboguer une application


Il est trs important de tester (on dit aussi  dboguer ) vos applications an de vous
assurer que vous avez envisag toutes les situations. Par exprience, je peux vous assurer
que les utilisateurs font souvent des manipulations  tranges  et parfois totalement
illogiques. Au-del de a, vous n'tes pas l'abri d'une erreur dans votre code. Il est
donc capital de tester et de retester vos applications avant de les distribuer.
Pour cela, vous utiliserez le volet de dbogage de Xcode. Grce lui, vous pourrez
contrler la valeur des variables utilises dans l'application pendant son excution.
Pour acher le volet de dbogage, il sut de cliquer sur l'icne Hide or show the
Debug area, dans la barre d'outils de Xcode, comme le montre la gure 23.1.

Figure 23.1  Achage du volet de dbogage

Achage d'informations depuis le code


Une des faons les plus simples d'acher des lments textuels dans le volet de dbogage
consiste utiliser la fonction NSLog() :
1

NSLog ( @ " texte afficher " ) ;

Si vous voulez acher le contenu d'une variable, vous devez prciser son type dans les
guillemets, puis indiquer la variable acher la suite du deuxime guillemet. Par
exemple, pour acher la valeur d'une variable de type int, vous pouvez crire quelque
chose comme ceci :
1

NSLog ( @ " Le r sultat est : % i " , resultat ) ;

Ou encore, pour acher la valeur d'une variable de type NSString, vous pouvez crire
quelque chose comme a :
430

DBOGUER UNE APPLICATION

NSLog ( @ " Le r sultat est : % @ " , @ " un texte quelconque " ) ;

Le langage Objective-C peut utiliser de nombreux types de variables. Nous les avons
rsums dans le tableau ci-aprs.
Type

%@
%d, %i
%u
%f
%x, %X
%o
%p
%e
%s
%S
%c
%C
%lld
%llu
%Lf

Signication
NSString

Entier sign
Entier non sign
Float/double
Entier hexadcimal
Entier octal
Pointeur
Float/double en notation scientique
String C (bytes)
String C (unichar)
Caractre
Unichar

Long long
Long long non sign
Long double

Le texte acher peut contenir un ou plusieurs caractres de mise en forme, tels


qu'un passage la ligne ou une tabulation. Ces caractres sont appels  squences
d'chappement . Je les ai rsumes dans le tableau suivant.
Squence Eet

\n
\r
\t
\v
\\
\
\'

Ligne suivante
Paragraphe suivant
Tabulation horizontale
Tabulation verticale
Antislash
Guillemet dans une chane
Apostrophe dans une chane

Par exemple, cette instruction :


1

NSLog ( @ " Ce texte est affich \ n sur deux lignes " ) ;

Produit l'achage suivant dans le volet de dbogage :


[...] test [935:207] Ce texte est affich
sur deux lignes

431

CHAPITRE 23.

GESTION DES MATRIELS ET DES IDENTITS

NUMRIQUES

Achage d'informations depuis le volet de dbogage


Il est galement possible d'insrer un point d'arrt dans le code. Cliquez dans la marge,
gauche de la ligne de code sur laquelle vous voulez arrter l'excution. Une marque
bleue est ache, comme sur la gure 23.2.

Figure 23.2  La marque bleue dans la marge indique un point d'arrt dans le code

Lorsque vous lancez l'application, l'excution est arrte sur la ligne ainsi marque.
Pour avoir des informations sur un des objets manipuls dans l'application, tapez  po 
suivi du nom de l'objet dans la console.

Souscrire au programme de dveloppement iOS


Pourquoi devrais-je souscrire au programme de dveloppement iOS ?

Eh bien, sachez que c'est une tape ncessaire pour :


1. tester vos applications sur device (et non dans le simulateur iOS) ;
2. distribuer vos applications.
Une mauvaise nouvelle : le programme de dveloppement n'est pas gratuit. De plus,
Apple en propose trois dclinaisons et vous devrez choisir celle qui s'adapte vos
besoins.
Vous pouvez ainsi opter pour :
 la version standard individuelle : 79 euros par an ;
 la version standard entreprise : 79 euros par an ;
 la version grande entreprise : 199 euros par an.
La version standard individuelle

Elle fait partie du programme iOS Developer Program. Elle s'adresse aux dveloppeurs individuels. Par son intermdiaire, ils peuvent crer des applications iOS gratuites
ou commerciales, les tester sur un ou plusieurs devices (jusqu' 100), puis les distribuer
sur l'App Store sous leur propre nom.
432

SOUSCRIRE AU PROGRAMME DE DVELOPPEMENT IOS

L'App Store est le site Web ociel de vente d'applications pour iPhone, iPod
Touch, et iPad.

La version standard entreprise

Elle fait galement partie du programme iOS Developer Program, mais elle permet
de grer une quipe de dveloppeurs. Par son intermdiaire, une entreprise peut crer
des applications iOS gratuites ou commerciales, les tester sur un ou plusieurs devices
(jusqu' 100), puis les distribuer sur l'App Store sous le nom de l'entreprise.
La version grande entreprise

Elle fait partie du programme iOS Developer Enterprise Program. Elle est destine
aux entreprises de plus de 500 salaris. La distribution des applications se fait travers
une sorte d'App Store d'entreprise, et non via l'App Store d'Apple. Chaque application
peut tre dploye sur un nombre illimit de devices.
Pour souscrire la version standard individuelle ou standard entreprise, rendez-vous sur
la page iOS Developer Program, cliquez sur Enroll Now et suivez les tapes indiques
sur l'cran.

Version
standard
B
Code web : 621357


Pour souscrire la version grande entreprise, rendez-vous sur la page iOS Developer
Enterprise Program, cliquez sur Apply Now et suivez les tapes indiques sur l'cran.


Version
grande
entreprise
B
Code web : 332828

Souscription la version standard individuelle


titre d'exemple, et parce que ce cas correspond la majorit d'entre vous, nous allons
examiner le processus de souscription la version standard individuelle, c'est--dire au
programme ddi aux dveloppeurs individuels.
Pour souscrire un programme de dveloppement, vous devez au pralable
avoir rejoint la communaut des dveloppeurs Apple. Cette tape a t dcrite
dans la section  Les logiciels ncessaires  du chapitre 1 (page 12). Consultez
cette section si vous n'avez pas encore fait ce premier pas.

Rendez-vous sur la page iOS Developer Program et cliquez sur Enroll Now (gure
23.3).
Un message vous avertit que vous devez disposer d'un Mac quip d'un processeur Intel
et utiliser le systme d'exploitation Mac OS X Snow Leopard ou ultrieur. Cliquez sur
433

CHAPITRE 23.

GESTION DES MATRIELS ET DES IDENTITS

NUMRIQUES

Figure 23.3  Rendez-vous sur la page iOS


Now

Developer Program et cliquez sur Enroll

pour poursuivre votre inscription.


Vous devez maintenant vous situer dans l'univers Apple. Cochez la case correspondant
votre cas (gure 23.4) :
  I need to create...  si vous n'avez pas encore un identiant Apple ID ;
  I have an Apple ID...  si vous avez un Apple ID mais que vous n'avez pas
encore rejoint la communaut des dveloppeurs Apple ;
  I'm registered as...  si vous avez rejoint la communaut des dveloppeurs
Apple mais pas encore le iOS Developer Program ;
  I'm currently enrolled...  si vous avez dj adhr au Mac Developer Program et que vous voulez y ajouter le iOS Developer Program.
Si vous avez suivi mes indications, vous devez avoir rejoint la communaut des dveloppeurs Apple et vous tes sur le point d'adhrer au iOS Developer Program.
ce titre, slectionnez la troisime case et cliquez sur Continue.
Comme nous l'avons dit prcdemment, le iOS Developer Program peut s'appliquer
un dveloppeur individuel ou une entreprise. Dans la page suivante, vous devez
choisir l'une ou l'autre de ces deux options.
Comme vous pouvez le voir, le nom ach en face des applications dans l'App Store
sera dirent selon que vous vous enregistriez en tant que dveloppeur individuel ou
en tant qu'entreprise. Dans le premier cas, votre nom sera associ aux applications
postes sur l'App Store. Dans le deuxime cas, c'est le nom de votre socit qui leur
Continue

434

SOUSCRIRE AU PROGRAMME DE DVELOPPEMENT IOS

Figure 23.4  Cochez la case correspondant votre cas

sera associ.
Si vous vous enregistrez en tant que dveloppeur individuel et que, par la suite,
vous devenez une socit, vous pourrez changer votre statut en consquence
en vous connectant nouveau sur la page iOS Developer Program.

Cliquez sur Individual et entrez vos identiants Apple.


Dans la prochaine tape, vous devez entrer vos coordonnes, telles qu'elles apparaissent
sur votre carte de crdit. Compltez le formulaire pr-rempli et cliquez sur Continue.
Vous devez alors choisir le programme auquel vous voulez adhrer. Cochez la case iOS
Developer Program (gure 23.5) et cliquez sur Continue.
L'tape suivante rsume les informations que vous avez entres. Cette vrication effectue, cliquez sur Continue.
L'tape suivante dcrit les termes du contrat de licence entre vous et Apple. Vriez
que vous tes en accord avec tous ces termes, cochez la case By checking this box...
et validez en cliquant sur I Agree. L'cran suivant vous invite ajouter le programme
dans votre caddie. Cliquez sur Add to Cart. Cliquez enn sur Passer la commande
(gure 23.6).
Il se peut que vous soyez invits entrer vos identiants Apple. Dans ce cas,
tapez votre Apple ID et le mot de passe associ puis validez.

435

CHAPITRE 23.

GESTION DES MATRIELS ET DES IDENTITS

NUMRIQUES

Figure 23.5  Vous devez choisir le programme auquel vous voulez adhrer

Figure 23.6   Passer la commande 

436

SOUSCRIRE AU PROGRAMME DE DVELOPPEMENT IOS

Validez en cliquant sur Continuer trois reprises. Entrez les informations relatives
votre carte de paiement et validez. Aprs quelques instants, une page vous indique
que votre commande est en cours de traitement. Il ne vous reste plus qu' attendre sa
validation par Apple, ce qui devrait se faire dans les 24 prochaines heures.
Une fois votre souscription au programme de dveloppement valide par Apple, vous
recevez deux e-mails.
Le premier vous remercie d'avoir rejoint le programme de dveloppement iOS et donne
accs au portail des dveloppeurs Apple (gure 23.7).

Figure 23.7  Portail des dveloppeurs Apple

Cliquez sur Log in now pour accder au site ddi aux dveloppeurs. Vous y trouverez :
 des ressources techniques lies au dveloppement pour devices iOS ;
 un ensemble de questions/rponses sur la soumission des applications sur l'App
Store ;
 un forum ddi aux dveloppeurs, dans lequel vous pourrez poser vos questions et
consulter les questions/rponses des autres dveloppeurs ;
 un accs au portail d'approvisionnement, pour tester vos applications sur device ;
 un accs iTunes Connect, pour soumettre vos applications sur l'App Store ;
 un accs au support technique Apple.
Comme souvent en informatique, toutes ces ressources sont en anglais.
Rassurez-vous, l'anglais technique est bien plus simple que celui que vous
avez appris au lyce.

Le deuxime e-mail donne le lien permettant d'accder directement iTunes Connect


437

CHAPITRE 23.

GESTION DES MATRIELS ET DES IDENTITS

NUMRIQUES

(gure 23.8).

Figure 23.8  iTunes Connect

En cliquant sur le lien  iTunes Connect , vous pourrez grer facilement les applications
soumises l'App Store (ventes, contrats, taxes, etc.), comme le montre la gure 23.9.

Figure 23.9  Vous pourrez grer facilement les applications soumises l'App Store

Certicats et prols d'approvisionnement


Pour pouvoir tester vos applications sur un ou plusieurs devices, puis les poster sur
l'App Store, vous allez devoir crer des certicats et des prols d'approvisionne438

CERTIFICATS ET PROFILS D'APPROVISIONNEMENT

ment. Il y a de grandes chances pour que ces deux termes ne fassent pas partie de

votre vocabulaire (du moins en ce qui concerne l'univers iOS). Alors voyons sans plus
attendre de quoi il s'agit.
Les certicats sont stocks sur votre Mac. Ils permettent d'identier :
 un dveloppeur : certicat de dveloppement ;
 un compte de dveloppement : certicat de distribution.
Les prols d'approvisionnement sont stocks sur le device. Ils servent de lien entre un ou
plusieurs certicats, un identiant d'application et des priphriques, an de scuriser
la diusion d'applications. On distingue :
 les prols d'approvisionnement de dveloppement, qui permettent d'autoriser un ou
plusieurs dveloppeurs dployer une application sur des devices spciques ;
 les prols d'approvisionnement de dploiement qui permettent de diuser des applications plus grande chelle, notamment sur l'App Store, mais galement en mode
 in-house  l'intrieur d'une grande entreprise.

Crer un prol d'approvisionnement


Pour tester vos applications sur un device (et non dans le simulateur iOS), vous allez
devoir crer un prol d'approvisionnement sur le portail. . . Commencez par relier votre
device sur un port USB de votre Mac. L'application iTunes dmarre automatiquement.
Pour l'instant, vous n'en aurez pas besoin. Vous pouvez la fermer ou la replier pour
librer le bureau.
Lancez Xcode en cliquant sur son icne dans le dock. Droulez le menu Window et
cliquez sur Organizer. Cliquez si ncessaire sur l'icne Devices dans la barre d'outils
de l'application Organizer et slectionnez votre device dans le volet droit. Une bote de
dialogue similaire la gure 23.10 est ache.
Cliquez sur Use for Development. Connectez-vous sur le portail des dveloppeurs
Apple, entrez vos identiants et cliquez sur iOS Provisioning Portal, puis sur Launch
Assistant dans le cadre Get your application on an iOS... (gure 23.11).


Portail
des
dveloppeurs
B
Code web : 870612


Cette action lance l'assistant d'approvisionnement. Cliquez sur Continue, choisissez
un nom pour identier votre App ID et cliquez sur Continue (gure 23.12).
Dcrivez votre device et copiez-collez son identiant depuis la fentre Organizer dans
la fentre de l'assistant, comme indiqu la gure 23.13.
Cliquez sur Continue. L'assistant vous demande de lancer l'application Keychain, soit
 Trousseau d'accs  en franais.
Cliquez sur l'icne Applications dans le dock, puis sur l'icne Utilitaires dans le
dossier des applications. Lancez enn l'application Trousseau d'accs.
439

CHAPITRE 23.

GESTION DES MATRIELS ET DES IDENTITS

NUMRIQUES

Figure 23.10  Une bote de dialogue s'ache

Figure 23.11  Cliquez sur Launch

440

Assistant

CERTIFICATS ET PROFILS D'APPROVISIONNEMENT

Figure 23.12  Choisissez un nom pour identier votre App ID et cliquez sur Continue

Figure 23.13  Copiez-collez l'identiant

441

CHAPITRE 23.

GESTION DES MATRIELS ET DES IDENTITS

NUMRIQUES

Cette application va gnrer une demande de signature. Cette tape doit


s'eectuer une fois (et une seule) pour chaque device que vous utiliserez pour
tester vos applications.

Cliquez sur le menu Trousseau d'accs, pointez Assistant de certification et


cliquez sur Demander un certificat une autorit de certificat, comme la
gure 23.14.

Figure 23.14  Demander

un certificat une autorit de certificat

Cette action dclenche l'achage de la bote de dialogue Assistant de certification.


Assurez-vous que les zones Adresse lectronique de l'utilisateur et Nom commun
soient correctement remplies. Slectionnez l'option Enregistre sur disque et cochez
la case Me laisser indiquer les informations sur la bi-cl, comme sur la gure 23.15.

Figure 23.15  Remplissez la bote de dialogue Assistant

442

de certification

CERTIFICATS ET PROFILS D'APPROVISIONNEMENT

Je veux bien entrer les informations correspondant la bi-cl, mais j'ai un


petit problme : qu'est-ce qu'une bi-cl au juste ?

Les bi-cls sont composes d'une cl publique et d'une cl prive.


 La cl publique sert chirer des donnes. Elle n'est pas secrte et peut tre librement
partage avec tout le monde.
 La cl prive est la partie secrte d'une bi-cl. Elle sert dchirer des donnes. Elle
doit rester condentielle.
Les bi-cls utilisent un programme spcique pour transformer l'information contenue
dans un texte lisible en des donnes chires, et inversement. Cliquez sur Continuer
et choisissez le dossier dans lequel sera stock le certicat.
Cliquez sur Enregistrer et choisissez 2048 bits dans la zone de texte Dimension de
la cl et RSA dans la zone de texte Algorithme (gure 23.16).

Figure 23.16  Choisissez une dimension de cl et un algorithme


Qu'est-ce que la taille d'une cl ? Et pourquoi avoir choisi 2048

bits ?

La taille d'une cl est mesure en  bits , ou  informations binaires . Plus une cl


est grande, plus il est dicile de la dcrypter. Une taille avoisinant les 2000 bits est
approprie pour une cl que vous comptez utiliser pendant quelques annes. Si vous
dsirez utiliser votre cl plus longtemps, vous pouvez utiliser une cl de plus grande
taille. Par exemple de 3000 ou 4000 bits.
443

CHAPITRE 23.

GESTION DES MATRIELS ET DES IDENTITS

NUMRIQUES

Cliquez sur Continuer. Aprs un bref instant, l'Assistant vous informe que le certicat
a t enregistr sur votre disque dur. Vous pouvez cliquer sur Terminer pour fermer la
bote de dialogue de l'Assistant de certication.
Maintenant que le certicat a t cr, vous pouvez retourner dans l'Assistant d'approvisionnement. Cliquez sur Continue, sur Choisir le fichier, dsignez le certicat
puis cliquez sur Continue. Vous devez maintenant donner un nom au prol d'approvisionnement. la gure 23.17, j'ai choisi  iPhone3G .

Figure 23.17  Il faut donner un nom au prol d'approvisionnement

Cliquez enn sur Generate. Au bout de quelques secondes, le prol est gnr, comme
la gure 23.18.
Cliquez sur Continue. La prochaine tape va consister tlcharger le prol d'approvisionnement dans votre Mac, puis l'installer sur votre device. Cliquez sur Download.
Une fois le chier tlcharg, cliquez dessus avec le bouton droit de la souris dans la
fentre Tlchargements et slectionnez Afficher dans le Finder. Assurez-vous que
votre device est connect au Mac, puis glissez-dposez le chier sur l'icne Xcode du
dock (gure 23.19). Cette action dclenche l'installation du chier d'approvisionnement
dans le device.
Retournez dans l'Assistant d'approvisionnement et cliquez sur Continue deux reprises. Maintenant, vous pouvez vrier que votre prol est bien ach dans la section
Provisioning de la fentre Organizer de Xcode, comme la gure 23.20.
Retournez dans l'Assistant d'approvisionnement et cliquez sur Continue. Vous tes
maintenant invits tlcharger le certicat de dveloppement iOS sur le Mac (gure
23.21). Cliquez sur Download.
444

CERTIFICATS ET PROFILS D'APPROVISIONNEMENT

Figure 23.18  Le prol est gnr

Figure 23.19  Glissez-dposez le chier sur l'icne Xcode du dock

445

CHAPITRE 23.

GESTION DES MATRIELS ET DES IDENTITS

NUMRIQUES

Figure 23.20  Le prol est bien ach

Figure 23.21  Vous tes invits tlcharger le certicat de dveloppement iOS sur

le Mac
446

CERTIFICATS ET PROFILS D'APPROVISIONNEMENT

Au bout de quelques instants, un chier nomm developer_identy.cer est tlcharg


et plac dans le dossier Tlchargements de votre Mac. Double-cliquez sur ce chier
et ajoutez le certicat un trousseau (gure 23.22).

Figure 23.22  Ajoutez le certicat un trousseau

Cliquez sur Ajouter. L'Assistant d'approvisionnement vous demande de vrier que


les cls prives et publiques ont bien t gnres et lies au certicat de dveloppeur.
Rendez-vous dans la fentre Trousseau d'accs et cliquez sur Cls dans le groupe
Catgorie. Vous devriez obtenir quelque chose ressemblant la gure 23.23.

Figure 23.23  Les cls sont bien prsentes

Retournez dans l'Assistant d'approvisionnement et cliquez sur Continue. La prochaine


fentre (gure 23.24) vous montre comment installer votre application avec Xcode.
Il ne vous reste plus qu' installer votre application sur le device. Cliquez sur Continue
puis sur Done.
447

CHAPITRE 23.

GESTION DES MATRIELS ET DES IDENTITS

NUMRIQUES

Figure 23.24  La fentre vous montre comment installer l'application avec Xcode

J'espre que vous avez tenu le coup : l'tape que nous venons de voir est longue mais
ncessaire pour l'installation d'une application sur un device.

Travailler sur un device


Installer une application iOS sur un device depuis Xcode
Voici les tapes qui vous permettront d'installer une application iOS sur un device qui
possde un certicat.
1. Connectez votre device au Mac via un port USB.
2. Ouvrez, dans Xcode, l'application que vous voulez installer sur votre device.
3. Droulez le menu Window et cliquez sur Organizer. Cette action ache la fentre
Organizer. Cliquez sur votre device dans la marge gauche et reprez la version
d'iOS installe sur ce device.
4. Refermez la fentre Organizer.
5. De retour dans Xcode, cliquez sur la premire icne dans le volet de navigation
et choisissez la mme version d'iOS dans la liste Deployment Target.
6. Slectionnez votre device dans la liste droulante Scheme, comme sur la gure
23.25.
7. Cliquez sur Run.
448

TRAVAILLER SUR UN DEVICE

Figure 23.25  Slectionnez votre device dans la liste droulante Scheme

Une bote de dialogue vous signale qu'une cl de votre trousseau va tre utilise pour
signer l'application. Validez en cliquant sur Autoriser, comme la gure 23.26.

Figure 23.26  Une bote de dialogue signale qu'une cl de trousseau va tre utilise
pour signer l'application

L'application est compile, copie sur le device puis excute.

Installer la dernire version de iOS sur un matriel


Connectez votre device un port USB du Mac. L'application iTunes se lance automatiquement. Slectionnez votre device dans le volet gauche de iTunes, sous le libell
APPAREILS. La version d'iOS est ache dans la partie droite de la fentre. Si une
mise jour est disponible, elle est ache dans le cadre Version. Il vous sut alors
de cliquer sur Mettre jour.

Faire des captures d'cran


Il est trs simple de faire une capture d'cran sur un iPhone, un iPod Touch ou un
iPad : appuyez simultanment sur les boutons Menu et Verrouillage, comme le montre
la gure 23.27.
Vous devriez entendre le son qui est habituellement mis lorsque vous prenez une photo.
C'est bon signe ! Cela veut dire que la capture d'cran s'est bien faite.
449

CHAPITRE 23.

GESTION DES MATRIELS ET DES IDENTITS

NUMRIQUES

Figure 23.27  Il faut appuyer simultanment sur les boutons Menu et Verrouillage

pour faire une capture d'cran

450

TRAVAILLER SUR UN DEVICE

Pour accder la capture, lancez l'application iPhoto et cliquez sur votre device, sous
APPAREILS. Slectionnez les photos importer sous Nouvelles photos (1) et cliquez
sur Importer la slection (2) (23.28).

Figure 23.28  La capture est prsente dans l'application iPhoto


Vous pouvez galement cliquer sur le deuxime bouton Importer pour importer toutes les photos aches sous Nouvelles photos.

En rsum
 Pour dboguer une application, rien de tel que le volet de dbogage de Xcode. Pour
l'acher, il sut de cliquer sur l'icne Hide or show the Debug area.
 L'instruction NSLog() permet d'acher des donnes alphanumriques dans le volet
de dbogage. Prcisez le type de la donne acher en utilisant un code %. Par
exemple %@ pour acher un NSString, ou encore %f pour acher un float ou un
double.
 Pour obtenir des informations depuis le volet de dbogage, insrez un point d'arrt
dans le code. Une fois l'application stoppe sur le point d'arrt, tapez la commande
po objet dans le volet de dbogage (o objet reprsente l'objet sur lequel vous
voulez avoir des informations).
 Pour pouvoir tester les applications que vous dveloppez sur vos devices (mais aussi
les diuser dans l'App Store), vous devez souscrire au programme de dveloppement
iOS.
451

CHAPITRE 23.

GESTION DES MATRIELS ET DES IDENTITS

NUMRIQUES

 Pour pouvoir tester vos applications sur un device, vous devez crer un prol d'approvisionnement.
 Pour installer une application sur un device, il sut de lancer la construction sur ce
device (liste droulante Scheme dans Xcode).
 Pour mettre jour iOS sur un device, connectez-le votre Mac, slectionnez-le dans
iTunes, sous APPAREILS, puis cliquez sur Mettre jour.
 Pour faire une capture d'cran sur un device, appuyez simultanment sur les boutons
Menu et Verrouillage. La capture est rcupre dans l'application iPhoto, aprs
avoir cliqu sur votre device sous APPAREILS.

452

Chapitre

24

Proposer une application sur l'App


Store
Dicult :

a y est, votre application est nalise et vous tes prts la diuser sur l'App
Store ? De nombreuses tapes prliminaires sont ncessaires. Assez fastidieuses et
partiellement expliques dans l'aide d'Apple, je vais faire mon possible pour vous les
expliquer aussi simplement que possible.

453

CHAPITRE 24.

PROPOSER UNE APPLICATION SUR L'APP STORE

Prparation prliminaire
L'organigramme ci-aprs reprsent la gure 24.1 rsume les principales tapes ncessaires pour proposer une application sur iTunes. N'hsitez pas vous y rfrer tout
au long de ce chapitre pour suivre votre avancement.

Figure 24.1  Les principales tapes ncessaires pour proposer une application sur

iTunes
454

PRPARATION PRLIMINAIRE

La distribution d'applications sur l'App Store se fait via le site Web iTunes
Connect. Par son intermdiaire, vous indiquerez vos renseignements scaux
et bancaires, vous dnirez des contrats pour vos applications, vous acherez
vos rapports de ventes et bien d'autres choses encore. . .

La premire tape consiste bien entendu crire votre application et la mettre au


point dans le simulateur.
Si vous lisez ces lignes, c'est que votre application a t teste et reteste et qu'elle est
prte tre diuse dans le vaste monde (ou alors que vous tes juste curieux). Pas de
prcipitation ! Deux tapes pralables sont ncessaires. Vous devez :
1. avoir souscrit au programme de dveloppement standard (ou suprieur) ;
2. vous connecter sur le site iTunes Connect, entrer les informations administratives ncessaires et obtenir un certicat de distribution pour l'application.
Si vous n'avez pas encore souscrit un programme de dveloppement (ce qui m'tonnerait fort), consultez la section intitule  Souscrire au programme de dveloppement
iOS  du chapitre prcdent (page 432).

Paramtrage de iTunes Connect


Ouvrez votre navigateur Web et connectez-vous sur iTunes

iTunes Connect

Connect.

web : 999498

Entrez vos identiants (Apple ID et mot de passe) puis cliquez sur Sign In. Cette
tape franchie, le navigateur donne accs au portail iTunes Connect, reprsent la
gure 24.2.

Code

Lors de votre premire connexion iTunes Connect, vous devrez approuver


les conditions d'utilisation. Ce n'est qu' cette condition que vous pourrez
utiliser iTunes Connect. Lisez bien le contrat d'utilisation et validez.

Contrats, taxes et informations bancaires

Cliquez sur Contracts, Tax and Banking ; vous arrivez sur la page reprsente la
gure 24.3. Tous les contrats achs doivent apparatre sous Contracts In Effect.
Si certains apparaissent sous Contracts In Progress, cela signie que les services
correspondants ne sont pas utilisables, car les informations ncessaires n'ont pas t
dnies.
Dans cet exemple, les informations relatives aux paiements (iOS Paid Applications)
et au systme de bannires publicitaires iAD n'ont pas t renseignes. Cliquez sur les
boutons Set Up correspondants et dnissez les informations demandes.
455

CHAPITRE 24.

PROPOSER UNE APPLICATION SUR L'APP STORE

Figure 24.2  Le portail iTunes

Figure 24.3  Contracts,

456

Connect

Tax and Banking

PRPARATION PRLIMINAIRE

Une fois toutes les informations ncessaires fournies, le statut des contrats devient
 Processing . Vous serez informs par e-mail lorsque les contrats seront valids et
actifs. La page Contracts, Tax and Banking se prsentera alors comme la gure
24.4.

Figure 24.4  Le statut des contrats est  Processing 


Obtenir le certicat de distribution

Dans la section  Crer un prol d'approvisionnement  du chapitre prcdent, vous


avez appris dnir puis mettre en place un prol d'approvisionnement pour tester
vos applications sur un device. Eh bien, vous allez devoir faire une manipulation similaire pour obtenir un prol d'approvisionnement qui vous permettra de poster vos
applications sur l'App Store.
Cration d'une demande de certicat

Cliquez sur l'icne Applications dans le dock. Ouvrez le dossier Utilitaires et


cliquez sur l'icne Trousseau d'accs. Lancez la commande Prfrences dans le
menu Trousseau d'accs. Basculez sur l'onglet Certificats et assurez-vous que les
deux premiers paramtres ont pour valeur Dsactiv(e), comme la gure 24.5, puis
fermez la bote de dialogue Prfrences.
Droulez le menu Trousseau d'accs, pointez Assistant de certification et cliquez sur Demander un certificat une autorit de certificat. Cette commande
provoque l'achage de la bote de dialogue Assistant de certification (gure
24.6). Remplissez cette bote de dialogue comme ceci :
457

CHAPITRE 24.

PROPOSER UNE APPLICATION SUR L'APP STORE

Figure 24.5  Les deux premiers paramtres ont pour valeur Dsactiv(e)

 entrez l'adresse e-mail utilise lorsque vous vous tes enregistrs en tant que dveloppeur dans la zone de texte Adresse lectronique de l'utilisateur ;
 entrez le nom utilis lorsque vous vous tes enregistrs en tant que dveloppeur dans
la zone de texte Nom commun ;
 laissez la zone de texte Adresse lectronique de l'AC vide ;
 slectionnez le bouton radio Enregistre sur disque et cochez la case Me laisser
indiquer les informations sur la bi-cl.

Figure 24.6  La bote de dialogue Assistant

de certification

Cliquez sur Continuer. L'Assistant donne un nom au certicat. Choisissez un emplacement pour le sauvegarder, puis cliquez sur Enregistrer.
458

PRPARATION PRLIMINAIRE

Dans la bote de dialogue suivante (gure 24.7), slectionnez 2048 bits dans la liste
droulante Dimension de cl, et RSA dans la liste droulante Algorithme, cliquez sur
Continuer, puis sur Terminer. Le certicat a t cr et sauvegard l'emplacement
choisi.

Figure 24.7  Choisissez les paramtres de la bi-cl


Soumission de la demande de certicat

Connectez-vous sur le portail des dveloppeurs Apple, entrez vos identiants et cliquez sur iOS Provisioning Portal, sur Certificates dans le menu de gauche, puis
slectionnez l'onglet Distribution.


Portail
des
dveloppeurs
B
Code web : 870612


Cliquez sur Request certificate puis sur Choisir. Dsignez le chier qui a t cr
l'tape prcdente (CertificateSigningRequest.certSigningRequest) puis cliquez
sur Submit. Au bout de quelques secondes, le certicat est ach dans le navigateur,
comme la gure 24.8.
Cliquez sur Click here to download now pour le tlcharger et enregistrez-le o bon
vous semble. Un chier nomm AppleWWDRCA.cer est ainsi cr. Double-cliquez sur ce
chier pour ouvrir l'application Trousseau d'accs et installer le certicat.
Toujours dans la page iOS Provisioning Portal, cliquez sur le bouton Download
ach dans la partie droite de la fentre. Une bote de dialogue de tlchargement
est ache. Sauvegardez le chier distribution_identity.cer o bon vous semble.
Une fois le chier tlcharg, double-cliquez dessus pour ouvrir l'application Trousseau
459

CHAPITRE 24.

PROPOSER UNE APPLICATION SUR L'APP STORE

Figure 24.8  Le certicat est ach dans le navigateur


d'accs

et installer le certicat de distribution.

Cration et tlchargement du prol de distribution iOS pour l'App Store

Connectez-vous sur le site iOS Developer Portal. Cliquez sur Member Center et entrez vos identiants. Cliquez sur Provisioning dans la partie gauche de la fentre et
slectionnez l'onglet Distribution.


iOS
Developer
Portal
B
Code web : 621357


Cliquez sur New Profile. En face de Distribution Method, slectionnez le bouton
radio App Store et compltez les informations demandes.
Cliquez sur Submit. Le prol de distribution est ach dans le navigateur avec un
statut Pending, comme la gure 24.9.
Il ne vous reste plus qu' patienter jusqu' l'activation de ce prol. Une fois activ,
cliquez sur Download pour le tlcharger, puis glissez-dposez l'icne du chier tlcharg sur celle de Xcode dans le dock. Cette action provoque l'achage de la fentre
Organizer, dans laquelle apparat votre prol de distribution (gure 24.10).

Prparer une application pour la diusion


Pour qu'une application puisse tre soumise l'App Store, deux actions doivent tre
eectues dans Xcode :
1. prparation du chier plist ;
460

PRPARATION PRLIMINAIRE

Figure 24.9  Le prol de distribution est ach dans le navigateur avec un statut
Pending

Figure 24.10  La fentre Organizer s'ache

461

CHAPITRE 24.

PROPOSER UNE APPLICATION SUR L'APP STORE

2. archivage.
Prparation du chier plist

Dveloppez le dossier Supporting files dans le volet de navigation et cliquez sur


nom-info.plist (o nom reprsente le nom de votre application).
Assurez-vous que la cl Bundle version contient la version de votre application (1.0
si vous publiez cette application pour la premire fois). Vriez qu'une icne a bien t
dnie pour votre application. Dans ce cas, les cls Icon files et Icon files (iOS
5) doivent tre direntes de 0.
Cliquez du bouton droit dans la partie droite de la fentre et slectionnez Add Row
dans le menu contextuel.
Dnissez la cl CFBundleIconFile. Lorsque vous appuyez

sur la touche Entre  de votre clavier, CFBundleIconFile se transforme en Icon
file. Double-cliquez dans la partie Value de cette nouvelle cl et entrez le nom de
l'icne de l'application.
Nettoyage et archivage

Lancez la commande Clean dans le menu Product pour  nettoyer  l'application,


c'est--dire la dbarrasser des ventuelles rfrences vers des lments qui auraient t
supprims.
Slectionnez iOS Device dans la liste droulante Scheme, dans l'angle suprieur gauche
de la fentre de Xcode, comme indiqu la gure 24.11.

Figure 24.11  Slectionnez iOS

Device

dans la liste droulante Scheme

Lancez la commande Edit Scheme dans le menu Product. Cette commande ache la
bote de dialogue Scheme. Basculez sur l'onglet Archive dans le volet gauche et vriez
que la valeur Release est slectionne dans la liste droulante Build Configuration.
Si ncessaire, modiez le nom de l'application dans la zone de texte Archive Name.
Assurez-vous que la case Reveal Archive in Organizer est coche (gure 24.12),
puis cliquez sur OK.
Lancez la commande Archive dans le menu Product. Lorsque la compilation est termine, l'application est ache dans la fentre Organizer, sous l'onglet Archives,
comme le montre la gure 24.13.
462

PRPARATION PRLIMINAIRE

Figure 24.12  Cochez la case Reveal

Archive in Organizer

Figure 24.13  L'application est ache dans la fentre Organizer

463

CHAPITRE 24.

PROPOSER UNE APPLICATION SUR L'APP STORE

Conguration de iTunes Connect


Documents et images ncessaires
Lors du rfrencement de l'application sur iTunes Connect, vous aurez besoin de plusieurs lments textuels et graphiques. Mieux vaut les rassembler avant de vous rendre
sur iTunes Connect.
 crivez un texte pour dcrire votre application (Apple recommande que ce texte ne
dpasse pas 700 caractres).
 Choisissez un nombre unique pour votre application. Vous pouvez par exemple choisir la date de soumission de l'application. Par exemple  23112011 . moins que
vous ne soumettiez plusieurs applications dans la mme journe. . . ce numro sera
eectivement unique.
 Eectuez entre une et quatre captures d'cran. Ces images doivent avoir une taille
de 640 x 960 pixels si l'application est destine aux iPhone ou iPod Touch. Elles
doivent avoir une taille de 1024 x 768 pixels si l'application est destine aux iPad.
 Dnissez une image JPEG de 512 x 512 pixels. Cette image doit tre aussi proche
que possible de l'icne de l'application.
Une fois tous ces lments en votre possession, vous tes prts pour la prochaine tape :
le rfrencement de l'application dans iTunes Connect.

Rfrencer l'application dans iTunes Connect


Ouvrez votre navigateur Web et connectez-vous sur iTunes Connect. Entrez vos identiants (Apple ID et mot de passe) puis cliquez sur Sign In.


iTunes
Connect
B
Code web : 999498


Cliquez sur Manage your applications, puis sur Add New App.
Entrez la langue de dveloppement (la langue utilise pour donner les dtails de l'application) et le nom de socit ou de dveloppeur que vous souhaitez voir apparatre
dans l'App Store pour toutes vos applications.
Ces deux informations ne peuvent pas tre facilement changes. Soyez srs
que vous faites le bon choix. Si vous avez fait une erreur, il vous reste nanmoins une solution : vous pouvez passer par le service aprs-vente d'Apple. . .
aux tats-Unis !

Cliquez sur Continue. Vous devez maintenant indiquer le nom de l'application (App
Name), un nombre unique associ l'application (SKU Number), l'identiant Bundle ID
(Bundle ID), et un ventuel suxe pour le Bundle ID, tel qu'il a t dni dans le
chier Info.plist (voir  Prparation du chier plist  plus haut).
Le champ SKU Number n'est pas utilis dans l'App Store. Il s'agit d'une rfrence pour
vous aider identier vos applications. Il peut tre constitu d'une chane alphanum464

CONFIGURATION DE

ITUNES CONNECT

rique quelconque. La date de publication par exemple.


Si vous n'avez pas encore dni un Bundle ID (c'est--dire un identiant pour votre
application), reportez-vous la section suivante. Dans le cas contraire, slectionnez le
Bundle ID de l'application dans la liste droulante (gure 24.14). Assurez-vous qu'il
correspond bien l'identiant de votre application, car il ne sera pas possible de le
modier par la suite.

Figure 24.14  Slectionnez le Bundle ID de l'application dans la liste droulante


Dnition d'un Bundle ID

Si vous n'avez pas encore dni un Bundle ID pour votre application, cliquez sur You
can register a new Bundle ID here sur la fentre de l'tape prcdente.
Dnissez :
 un nom pour identier l'App ID (Description) ;
 un identiant (Bundle Identifier). Gnralement, cet identiant est constitu de
votre nom de domaine invers suivi d'un point dcimal et du nom de l'application.
la gure 24.15, j'utilise mon propre nom de domaine, c'est--dire le nom de domaine
du site sur lequel je vais parler de mes applications (mediaforma.com) que j'inverse
(com.mediaforma), et je le fais suivre du nom de l'application (com.mediaforma.w7at1).
Cliquez sur Submit.
Le Bundle ID est immdiatement cr, mais, comme le montre la gure 24.16, vous
devez le congurer pour le dveloppement et pour la production.
Cliquez sur Configure. Cochez la case Enable for Apple Push Notification service
et cliquez sur le bouton Configure, en face de Production Push SSL Certificate.
465

CHAPITRE 24.

PROPOSER UNE APPLICATION SUR L'APP STORE

Figure 24.15  Dnition d'un Bundle ID

Figure 24.16  Vous devez congurer le Bundle ID

466

CONFIGURATION DE

ITUNES CONNECT

Dsignez le chier CertificateSigningRequest.certSigningRequest qui a t cr


dans une tape prcdente et validez.
Le certicat de production a t valid, il ne vous reste plus qu' le tlcharger en
cliquant sur le bouton Download.
Cliquez sur Continue. Au bout de quelques secondes, un nouvel cran est ach. Indiquez le jour de disponibilit de l'application (le jour actuel gnralement). Choisissez
le niveau de prix dans la liste droulante Price Tier. Si ncessaire, cliquez sur View
Pricing Matrix pour voir la grille de prix, visible la gure 24.17.

Figure 24.17  La grille des prix


Cette capture d'cran a volontairement t coupe car bien trop large. J'ai
ralis cette coupure pour faire apparatre la colonne Tier et la colonne
Europe - Euro, qui contient les informations qui nous intressent.

Dcochez la case Discount for Educational Institutions si vous ne voulez pas


qu'un rabais de 20 % soit accord aux tablissements scolaires.
Cliquez sur Continue et entrez les informations demandes, comme indiqu la gure
24.18.
 Le champ Version Number indique le numro de version de l'application. Ce numro
doit suivre les standards de numrotation : 1.0, 1.1, 2.0, etc. N'utilisez pas un libell
 alpha  ou  beta  pour dire que l'application est en phase de test.
 Le champ Description contient le texte qui sera ach dans l'App Store.
 Slectionnez la catgorie principale de l'application et ventuellement une souscatgorie (si vous avez choisi la catgorie Games).
 Choisissez des mots-cls spars par des virgules (jusqu' 100 caractres). Choisissez467

CHAPITRE 24.









PROPOSER UNE APPLICATION SUR L'APP STORE

les prudemment : ils feront ressortir l'application lors de recherches des utilisateurs
dans l'App Store. De plus, ils ne pourront pas tre changs jusqu' ce qu'une nouvelle
version de l'application soit disponible.
Le champ Contact Email Address sera utilis par Apple si les validateurs ont des
questions sur votre application.
Dans le champ Support URL, entrez l'URL acher dans l'App Store pour le support
de l'application. Assurez-vous que cette URL correspond une page Web existante.
Vous pouvez galement saisir une URL ddie l'application (App URL), et/ou
une URL ddie si vous utilisez In App Purchase dans votre application (Privacy
Policy URL).
Le champ Review Notes est destin aux personnes qui vont valider votre application.
Entrez tout commentaire que vous jugerez utile, ou laissez cette zone vide.
Assurez-vous que toutes les cases sous App Rating Detail sont sur None et que cela
correspond bien votre application.
Si vous voulez dnir un contrat de licence d'utilisateur nal, entrez le texte correspondant dans la zone EULA text (EULA est l'abrviation de End User License
Agreement, soit en franais  Contrat de licence d'utilisateur nal ) et slectionnez
les pays concerns par la licence.
Sous Uploads, vous devez fournir une icne de 512 x 512 pixels au format PNG,
ainsi qu'une ou plusieurs captures d'cran sur iPhone et/ou iPad, selon la cible de
l'application.
Vous pouvez fournir jusqu' cinq captures d'cran dans les sections iPhone
and iPod Touch Screenshots et iPad Screenshots. Si ncessaire, les
captures d'cran peuvent tre dplaces avec la technique du glisser-dposer
pour tre mises dans l'ordre d'apparition souhait sur l'App Store.

Cliquez sur Save. Votre application est maintenant prte tre propose aux validateurs chez Apple. Le statut de l'application est  Prepare for upload . Cliquez sur View
Details puis sur Ready to Upload Binary. Aprs quelques instants, l'application a
le statut  Waiting for Upload  (gure 24.19).

468

CONFIGURATION DE

ITUNES CONNECT

Figure 24.18  Entrez les informations demandes

Figure 24.19  L'application a le statut  Waiting for Upload 

469

CHAPITRE 24.

PROPOSER UNE APPLICATION SUR L'APP STORE

Validation et soumission d'une application


Vous voil dans la dernire ligne droite. la n de cette section, vous saurez comment
valider et soumettre une application sur l'App Store.
Ouvrez Xcode et cliquez sur l'icne Organizer dans l'angle suprieur droit de la fentre.
Cette action ache la fentre Organizer. Basculez sur l'onglet Archives. L'application
valider et soumettre doit apparatre dans cette fentre, comme la gure 24.20.

Figure 24.20  L'application valider et soumettre doit apparatre dans la fentre


Organizer

Cliquez sur Validate. Aprs quelques instants, si tout se passe bien, le statut de
l'application deviendra Passed Validation. Si des problmes sont dtects pendant
la validation, une bote de dialogue semblable la gure 24.21 sera ache.
Corrigez les erreurs et recommencez la validation. Une fois que tout est correct, une
fentre devrait s'acher vous disant que tout est bon.
Lorsque le statut de l'application est Passed Validation, cliquez sur Submit. L'application aura alors le statut Submitted dans la fentre Organizer et Waiting for
Review dans iTunes Connect.
Il ne vous restera plus qu' attendre que votre application soit valide par l'quipe de
l'App Store. En gnral, le dlai ncessaire est d'environ une semaine. . .

470

VALIDATION ET SOUMISSION D'UNE APPLICATION

Figure 24.21  Des problmes ont t dtects lors de la validation

Quand votre application est accepte. . .


Lorsque votre application est accepte sur l'App Store, vous recevez un e-mail indiquant
 Your application is ready for sale , c'est--dire  Votre application est prte tre
commercialise . Je vous conseille de retourner dans iTunes Connect. Entrez vos
identiants et connectez-vous. Cliquez sur Manage Your Applications, puis cliquez
sur l'icne de l'application pour accder ses informations.
Cliquez sur Rights and Pricing et changez la date de disponibilit de votre application en la remplaant par sa date d'approbation dans l'App Store. Ainsi, vous apparatrez en tte des applications publies sur l'App Store.
Cette technique est trs intressante, mais elle ne peut tre applique qu'une
fois, pour faire correspondre la date de publication avec la date d'approbation.

Si vous le souhaitez, vous pouvez modier plusieurs informations concernant votre


application (descriptions, copies d'cran, prix) et ce, sans devoir passer par le processus
d'approbation.
Il n'est pas possible de changer les mots-cls associs l'application, moins
de publier une mise jour de l'application.

471

CHAPITRE 24.

PROPOSER UNE APPLICATION SUR L'APP STORE

Si vous avez cr une page pour faire la promotion de votre application, vous pouvez
y insrer un lien permettant vos visiteurs de l'acheter. Ce lien devra tre le suivant :
http :// itunes . apple . com / WebObjects / MZStore . woa / wa / viewSoftware ?
id = identifiant & mt =8

Dans cette URL, remplacez identifiant par l'identiant de votre application (celui-ci
vous a t communiqu dans l'e-mail  Ready for Sale ).
Il ne reste plus qu' faire autant de publicit que vous le pourrez pour promouvoir
votre application. Vous devriez en particulier songer parler de votre application sur
les rseaux sociaux, sur les sites Web ddis aux applications iOS, et dans les revues
spcialises (papier et en ligne).

Gagner de l'argent avec une application


Pour gagner de l'argent avec une application, vous pouvez :
1. la diuser gratuitement sur l'App Store et y inclure une bannire publicitaire
(iAd) ;
2. la vendre sur l'App Store.
En marge de ces deux modles, vous pouvez galement proposer une application gratuite, sans publicit. . . mais incomplte.
Placez-y un certain nombre de fonctionnalits qui donneront envie ses utilisateurs
d'acheter la version complte qui, elle, sera payante. En utilisant la technique  In-App
Purchase , l'achat pourra se faire depuis l'application gratuite. Si vous voulez en savoir
plus sur cette possibilit, consultez le site developper.apple.com.
B


developper.apple.com

Code

web : 919065

Insrer de la publicit dans une application


Pourquoi ennuyer vos utilisateurs avec des annonces publicitaires ? Eh bien tout simplement parce que de cette faon, vous pouvez leur proposer des applications gratuites
tout en gnrant un revenu. Le principe est simple : chaque fois qu'une annonce publicitaire est ache, vous tes rmunrs. vous de trouver un juste milieu pour que
vos utilisateurs ne soient pas trop drangs et continuent utiliser votre application
malgr l'achage des annonces publicitaires.
La taille de la bannire publicitaire dpend du mode d'achage de l'application et du
device utilis :
 En achage  Portrait  : 320 x 50 pixels sur iPhone et iPod Touch, 768 x 66 pixels
sur iPad.
472

GAGNER DE L'ARGENT AVEC UNE APPLICATION

 En achage  Paysage  : 480 x 32 pixels sur iPhone et iPod Touch, 1024 x 66 pixels
sur iPad.
Pour acher une bannire publicitaire dans une application, il sut d'utiliser le framework iAd. Voyons comment mettre cela en pratique.
Le framework iAd

Dnissez une nouvelle application de type Single View Application et donnez-lui


le nom  iAd . Dans un premier temps, vous allez insrer le framework iAd dans
l'application. Comme indiqu la gure 24.22, cliquez sur la premire icne dans le
volet de navigation (1) et slectionnez l'onglet Build Phases (2) dans la partie centrale
de la fentre. Dveloppez la zone Link Binary With Libraries (3), cliquez sur l'icne
+ (4) et ajoutez le framework iAd.framework (5).

Figure 24.22  Ajoutez le framework iAd

Le framework tant inclus dans l'application, vous allez y faire rfrence dans le chier d'en-ttes. Cliquez sur ViewController.h dans le volet de navigation et ajoutez
l'instruction #import suivante :
1

# import < iAd / iAd .h >

Pour traiter les vnements relatifs aux iAds, insrez le delegate ADBannerViewDelegate
dans la dnition de l'interface :
1

@interface ViewController : UIViewController <


ADBannerViewDelegate >

473

CHAPITRE 24.

PROPOSER UNE APPLICATION SUR L'APP STORE

Enn, dnissez la variable d'instance bannerView de classe ADBannerView :


ADBannerView * bannerView ;

Le chier d'en-ttes doit maintenant ressembler ceci :


1
2
3
4

# import < UIKit / UIKit .h >


# import < iAd / iAd .h >
@interface ViewController : UIViewController <
ADBannerViewDelegate >
@end

Vous allez maintenant ajouter une bannire publicitaire dans la vue 1 . Cliquez sur
MainSToryboard.storyboard dans le volet de navigation et ajoutez dans l'application
un contrle AdBannerView, comme la gure 24.23.

Figure 24.23  Ajoutez un contrle AdBannerView dans l'application

Cliquez sur l'icne Show the Assistant editor dans la barre d'outils et crez l'outlet
banner pour le contrle AdBannerView.
Le chier d'en-ttes doit maintenant contenir le code suivant :
1
2
3

# import < UIKit / UIKit .h >


# import < iAd / iAd .h >
1. Apple recommande de placer la bannire dans la partie suprieure ou infrieure de la vue.

474

GAGNER DE L'ARGENT AVEC UNE APPLICATION

4
5
6

@interface ViewController : UIViewController <


ADBannerViewDelegate >
@property ( weak , nonatomic ) IBOutlet ADBannerView * banner ;
@end

Il ne reste plus qu' crire quelques lignes de code pour implmenter la bannire publicitaire. Mais avant de vous mettre au travail, je vous suggre de consulter l'aide Apple
sur la classe ADBannerView et sur le protocole ADBannerViewDelegate. Vous aurez
ainsi une ide des mthodes utiliser.
Cliquez sur l'icne Organizer dans la barre d'outils de Xcode et faites une recherche
sur la classe ADBannerView. En parcourant le contenu de cette aide (gure 24.24),
vous voyez que vous devez prciser les dimensions de la bannire avec la proprit
requiredContentSizeIdentifiers.

Figure 24.24  L'aide d'Apple concernant la classe ADBannerView

Maintenant, parcourez l'aide sur le protocole ADBannerViewDelegate. Vous voyez que


plusieurs mthodes vnementielles seront gnres par la bannire. En particulier :
 bannerViewDidLoad, lorsque la bannire publicitaire a t charge ;
 bannerViewActionShouldBegin:willLeaveApplication :, lorsque l'utilisateur clique
sur la bannire publicitaire ;
 bannerViewActionDidFinish, lorsque l'utilisateur ferme l'encart publicitaire ;
 bannerView:didFailToReceiveAdWithError : appele si la bannire publicitaire n'a
pas pu tre charge.
475

CHAPITRE 24.

PROPOSER UNE APPLICATION SUR L'APP STORE

Lorsque l'utilisateur clique sur un encart publicitaire, la mthode


bannerViewActionShouldBegin:willLeaveApplication: est excute.
Selon les paramtres fournis cette mthode (tout ceci est prcis dans
l'aide), l'application peut alors passer en arrire-plan et la publicit s'acher.
Ce n'est qu'une fois que la publicit aura t vue et ferme par l'utilisateur
que l'application reprendra le contrle.

Mais assez palabr. Il est temps d'crire le code de l'application !


Cliquez sur ViewController.m dans le volet de navigation et compltez la mthode
viewDidLoad comme suit :
1
2
3
4
5
6

- ( void ) viewDidLoad
{
[ super viewDidLoad ];
banner . requiredContentSizeIdentifiers = [ NSSet setWithObjects
: ADBannerContentSizeIdentifierPortrait ,
ADBannerContentSizeIdentifierLandscape , nil ];
banner . delegate = self ;
}

La ligne 4 indique que l'application sera utilise en mode portrait et en mode paysage.
La ligne 5 indique que la gestion des vnements relatifs la bannire publicitaire sera
traite dans la classe courante.
Ajoutez les mthodes suivantes :
1
2
3
4
5
6
7
8
9
10
11
12

- ( BOOL ) bannerViewActionShouldBegin :( ADBannerView *) banner


willLeaveApplication :( BOOL ) willLeave
{
return YES ;
}
- ( void ) bannerViewActionDidFinish :( ADBannerView *) banner
{
}
- ( void ) bannerView :( ADBannerView *) banner
didFailToReceiveAdWithError :( NSError *) error
{
}

L'unique instruction de bannerViewActionShouldBegin:willLeaveApplication : demande que l'action relative la bannire soit excute. Une valeur NO aurait bloqu
cette action. Les deux autres mthodes ne contiennent aucune instruction, mais rien
ne vous empche de les complter pour eectuer des traitements spciques vos applications.
Il ne reste plus qu' modier la taille de la bannire en fonction de l'orientation du
device. Compltez le code comme ceci :
476

GAGNER DE L'ARGENT AVEC UNE APPLICATION

1
2
3
4
5
6
7
8

- ( BOOL ) shouldAutorotateToInterfaceOrientation :(
UIInterfaceOrientation ) interfaceOrientation
{
if ( UIInterfaceOrientationIsLandscape ( interfaceOrientation ) )
banner . currentContentSizeIdentifier =
ADBannerContentSizeIdentifierLandscape ;
else
banner . currentContentSizeIdentifier =
ADBannerContentSizeIdentifierPortrait ;
return YES ;
}

Si le device ache en mode paysage, la taille de la bannire est initialise en consquence. Si le device ache en mode portrait, la taille de la bannire est ajuste avec la
constante ddie ce mode d'achage. Il ne vous reste plus qu' lancer l'application.
Le rsultat se trouve en gure 24.25.

Figure 24.25  L'application avec la pub

Cette application se trouve dans le dossier iAd.




Copier
ce
code
B
Code web : 811925


ViewController.h
1
2

# import < UIKit / UIKit .h >


# import < iAd / iAd .h >

477

CHAPITRE 24.

3
4
5
6

PROPOSER UNE APPLICATION SUR L'APP STORE

@interface ViewController : UIViewController <


ADBannerViewDelegate >
@property ( weak , nonatomic ) IBOutlet ADBannerView * banner ;
@end

ViewController.m
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

# import " ViewController . h "


@implementation ViewController
@synthesize banner ;
- ( void ) didReceiveMemoryWarning
{
[ super didReceiveMemoryWarning ];
// Release any cached data , images , etc that aren 't in use .
}
# pragma mark - View lifecycle
- ( void ) viewDidLoad
{
[ super viewDidLoad ];
banner . requiredContentSizeIdentifiers = [ NSSet setWithObjects
: ADBannerContentSizeIdentifierPortrait ,
ADBannerContentSizeIdentifierLandscape , nil ];
banner . delegate = self ;
}
- ( void ) bannerViewDidLoadAd :( ADBannerView *) banner
{
// tableView . tableHeaderView = bannerView ;
}
- ( BOOL ) bannerViewActionShouldBegin :( ADBannerView *) banner
willLeaveApplication :( BOOL ) willLeave
{
return YES ;
}
- ( void ) bannerViewActionDidFinish :( ADBannerView *) banner
{
}
- ( void ) bannerView :( ADBannerView *) banner
didFailToReceiveAdWithError :( NSError *) error
{
}

478

GAGNER DE L'ARGENT AVEC UNE APPLICATION

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

- ( void ) viewDidUnload
{
banner = nil ;
[ self setBanner : 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
{
if ( UIInterfaceOrientationIsLandscape ( interfaceOrientation ) )
banner . currentContentSizeIdentifier =
ADBannerContentSizeIdentifierLandscape ;
else
banner . currentContentSizeIdentifier =
ADBannerContentSizeIdentifierPortrait ;
return YES ;
}
@end

En rsum
 Pour proposer Apple une application que vous avez dveloppe, vous devez successivement crire, tester et retester l'application, souscrire au programme Dveloppeurs,
saisir des informations administratives sur l'application dans iTunes Connect, obtenir un contrat de distribution pour l'application, prparer l'application pour la
479

CHAPITRE 24.

PROPOSER UNE APPLICATION SUR L'APP STORE

diusion, ajouter l'application dans iTunes Connect, valider puis soumettre l'application.
 Pour gagner de l'argent avec une application, vous pouvez la diuser gratuitement
sur l'App Store et y inclure une bannire publicitaire ou la vendre sur l'App Store.
 Pour acher une bannire publicitaire dans une application, vous utiliserez le framework iAd. Insrez un contrle AdBannerView dans l'application et traitez les vnements relatifs aux iAds via le delegate ADBannerViewDelegate.

480

Index
A

acclromtre . . . . . . . . . . . . . . . . . . . . . . . . 375
API. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .11
App Store . . . . . . . . . . . . . . . . . . . . . . . . . . . 453
Apple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
application multivues . . . . . . . . . . . . . . . . 142
arc4random . . . . . . . . . . . . . . . . . . . . . . . . . .120
array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .108
arrire-plan . . . . . . . . . . . . . . . . . . . . . . . . . . 341
audio
enregistrement . . . . . . . . . . . . . . . . . . 345
lecture . . . . . . . . . . . . . . . . . . . . . . . . . . 322
autocompltion . . . . . . . . . . . . . . . . . . . . . . 209
B

commentaire . . . . . . . . . . . . . . . . . . . . . . . . . . 52
condition. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .62
constante . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
contrles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
conversion de type . . . . . . . . . . . . . . . . . . . . 57
CoreLocation . . . . . . . . . . . . . . . . . . . . . . . 300
curseur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
D

date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
Date Picker . . . . . . . . . . . . . . . . . . . . . . . . .218
dbogage . . . . . . . . . . . . . . . . . . . . . . . . . 36, 430
dcrmentation. . . . . . . . . . . . . . . . . . . . . . . .49
device. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6
dictionnaire . . . . . . . . . . . . . . . . . . . . . . . . . . 113
do while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
documentation Apple . . . . . . . . . . . . . . . . 165
donnes
type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
double . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .53

bannire publicitaire . . . . . . . . . . . . . . . . . 472


barre de recherche . . . . . . . . . . . . . . . . . . . 255
boolen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
boucle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
do while . . . . . . . . . . . . . . . . . . . . . . . . .70
for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .68
E
while . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
bouton. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .224 chappement. . . . . . . . . . . . . . . . . . . . . . . . .431
else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
C
else if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
capture d'cran . . . . . . . . . . . . . . . . . . . . . . 449 en-ttes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
caractre. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .54 enregistrement audio . . . . . . . . . . . . . . . . . 345
carte. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .177 ensemble. . . . . . . . . . . . . . . . . . . . . . . . . . . . .116
casting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 entier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
chane de caractres . . . . . . . . . . . . . . . 56, 96
F
char . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 fentre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
Cocoa Touch . . . . . . . . . . . . . . . . . . . . . . . . . . 11 chier d'en-ttes . . . . . . . . . . . . . . . . . . . . . . 22
collision . . . . . . . . . . . . . . . . . . . . . . . . . 396, 419 float . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
481

INDEX

fonction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .71 objet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77, 91


fond d'cran . . . . . . . . . . . . . . . . . . . . . . . . . 341 onglet. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .226
for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 oprateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
G

golocalisation . . . . . . . . . . . . . . . . . . . . . . . 299 Page Control . . . . . . . . . . . . . . . . . . . . . . . 237


getter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 photo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366
Picker View . . . . . . . . . . . . . . . . . . . . . . . . .211
I
pointeur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 programmation . . . . . . . . . . . . . . . . . . . . . . . 10
image . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
oriente objet. . . . . . . . . . . . . . . . . . . . .77
Image View . . . . . . . . . . . . . . . . . . . . . . . . . .159 proprit. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .77
incrmentation . . . . . . . . . . . . . . . . . . . . . . . . 49 publicit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 472
indentation . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 publier une application. . . . . . . . . . . . . . .453
instruction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
int . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
R
Interface Builder . . . . . . . . . . . . . . . . . . . . . . 19 rel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
Interrupteur . . . . . . . . . . . . . . . . . . . . . . . . . 235
double . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
iOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
float . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
iPad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 ressources. . . . . . . . . . . . . . . . . . . . . . . . . . . .166
iPhone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
iPod Touch. . . . . . . . . . . . . . . . . . . . . . . . . . . . .8
S
sandbox
.
.
.
.
.
. . . . . . . . . . . . . . . . . . . . . . . . 169
L
screenshot
.
.
.
. . . . . . . . . . . . . . . . . . . . . . . . 449
Label . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .156
Scroll View . . . . . . . . . . . . . . . . . . . . . . . . .183
lecture audio. . . . . . . . . . . . . . . . . . . . . . . . .322 Search Bar . . . . . . . . . . . . . . . . . . . . . . . . . .255
Segmented Control . . . . . . . . . . . . . . . . . 226
M
Map View . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177 setter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
MapKit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 simulateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
actions . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
mthode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
gestuelles . . . . . . . . . . . . . . . . . . . . . . . . . 34
modulo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Slider
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
multimdia
son
.
.
.
.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
image . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
structure.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .57
son. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .321
switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .66
N

T
nombre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
Tab
Bar
.
.
.
.
.
. . . . . . . . . . . . . . . . . . . . . . . . 248
nombre alatoire . . . . . . . . . . . . . . . . . . . . . 120
Table
View
.
.
. . . . . . . . . . . . . . . . . . . . . . . .198
NSArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
tableau
.
.
.
.
.
.
.
. . . . . . . . . . . . . . . . . . . . . . . 108
NSLog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
Text
Field
.
.
.
. . . . . . . . . . . . . . . . . . 157, 230
NSNumber . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
Text
View
.
.
.
.
.
. . . . . . . . . . . . . . . . . . . . . . 159
NSString . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
Tool
Bar
.
.
.
.
.
.
.
. . . . . . . . . . . . . . . . . . . . . 251
NSURL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .176
O

Objective-C . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
482

UIKit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

INDEX

variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
type. . . . . . . . . . . . . . . . . . . . . . . . . . . . .431
vido . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358
volet de dbogage . . . . . . . . . . . . . . . . . . . . 430
vue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
W

Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
Web View . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
X

Xcode. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .12

483

Notes

Notes

Notes

Notes

Notes

Notes

Notes

Notes

Notes

Notes

Dpt lgal : avril 2012


ISBN : 979-10-90085-06-0
Code diteur : 979-10-90085
Imprim en France
Achev d'imprimer le 20 avril 2012
sur les presses de Corlet Imprimeur (Cond-sur-Noireau)
Numro imprimeur : 145543

Mentions lgales :
Crdit photo Michel Martin 4e de couverture : Fan Jiyong
Conception couverture : Fan Jiyong
Illustrations chapitres : Fan Jiyong
Ralisation designs casse-briques et  Capturez les vers  : Fan Jiyong