Vous êtes sur la page 1sur 239

Dveloppez des applications pour

iPhone

Lee
e S. Barney

avec HTML,
CSS et
JavaScript

iPhone Livre Page I Vendredi, 30. octobre 2009 12:04 12

L E

P R O G R A M M E U R

Dveloppez
des applications
pour liPhone
avec HTML, CSS et JavaScript
Lee S. Barney

Traduit par Herv Soulard,


avec la contribution de Julien Desrosiers

iPhone Livre Page II Vendredi, 30. octobre 2009 12:04 12

Pearson Education France a apport le plus grand soin la ralisation de ce livre afin de vous fournir une information complte et fiable. Cependant, Pearson Education France nassume de responsabilits, ni pour son utilisation, ni pour les contrefaons de brevets ou atteintes aux droits de tierces
personnes qui pourraient rsulter de cette utilisation.
Les exemples ou les programmes prsents dans cet ouvrage sont fournis pour illustrer les descriptions
thoriques. Ils ne sont en aucun cas destins une utilisation commerciale ou professionnelle.
Pearson Education France ne pourra en aucun cas tre tenu pour responsable des prjudices
ou dommages de quelque nature que ce soit pouvant rsulter de lutilisation de ces exemples ou
programmes.
Tous les noms de produits ou marques cits dans ce livre sont des marques dposes par leurs
propritaires respectifs.

Publi par Pearson Education France


47 bis, rue des Vinaigriers
75010 PARIS
Tl. : 01 72 74 90 00
www.pearson.fr

Titre original : Developing Hybrid Applications for the iPhone :


using HTML, CSS, and JavaScript to Build Dynamic Apps
for the iPhone
Traduit par Herv Soulard,
avec la contribution de Julien Desrosiers

Mise en pages : TyPAO


ISBN : 978-2-7440-4096-2
Copyright 2009 Pearson Education France
Tous droits rservs

ISBN original : 978-0-321-60416-3


Copyright 2009 Pearson Education, Inc.
All rights reserved
dition originale publie par Addison-Wesley

Aucune reprsentation ou reproduction, mme partielle, autre que celles prvues larticle L. 122-5 2 et 3 a) du code de la
proprit intellectuelle ne peut tre faite sans lautorisation expresse de Pearson Education France ou, le cas chant, sans le
respect des modalits prvues larticle L. 122-10 dudit code.
No part of this book shall be reproduced, stored in a retrieval system, or transmitted by any means, electronic, mechanical,
photocopying, recording, or otherwise, without written permission from the publisher.

iPhone Livre Page III Vendredi, 30. octobre 2009 12:04 12

Sommaire

Prface ....................................................

6. Cartes Google .....................................

133

1. Dvelopper avec Dashcode et Xcode

7. Bases de donnes ................................

151

2. Modularit JavaScript ......................

33

8. Donnes distantes ..............................

185

3. Interfaces utilisateur .........................

57

A. Introduction JSON ........................

205

B. Plan de dveloppement
pour QuickConnectFamily ..............

213

C. Plan de dveloppement
pour PhoneGap .................................

219

Index .......................................................

223

4. GPS, acclromtre
et autres fonctions natives
avec QuickConnectiPhone ...............
5. GPS, acclromtre
et autres fonctions natives
avec PhoneGap ..................................

91

115

iPhone Livre Page IV Vendredi, 30. octobre 2009 12:04 12

iPhone Livre Page V Vendredi, 30. octobre 2009 12:04 12

Table des matires

2. Modularit JavaScript ................................ 33

Prface ...............................................................
Outils pour le dveloppement
dapplications hybrides ..................................
Comment utiliser ce livre ...............................
Ressources en ligne .......................................
Prrequis ........................................................
Remerciements ..............................................
propos de lauteur ......................................
Contacter lauteur ..........................................

1. Dvelopper avec Dashcode et Xcode ...........


Section 1 : utiliser Dashcode
et le modle QuickConnect ............................
Section 2 : utiliser Xcode
et le modle QuickConnect ............................
Section 3 : les bases dObjective-C ...............
Section 4 : structure Objective-C dune
application QuickConnectiPhone ..................
Section 5 : structure Objective-C
dune application PhoneGap ..........................
Section 6 : embarquer du contenu web
avec QuickConnectiPhone .............................
Section 7 : embarquer du contenu web
avec PhoneGap ...............................................
En rsum ......................................................

Section 5 : implmentation
dun contrleur derreur ................................ 53

Section 6 : tapes de cration


dune fonctionnalit de lapplication ............. 54

Section 1 : modularit ................................... 33


1
3
5
5
6
6
6

Section 2 : modularit avec le framework


JavaScript QuickConnect ............................. 35
Section 3 : conception modulaire
dans QuickConnectiPhone ............................ 44
Section 4 : implmentation
des contrleurs mtier
et daffichage ................................................. 49

En rsum ...................................................... 55

12
16

3. Interfaces utilisateur ................................... 57

19

Section 1 : guide de linterface


utilisateur dApple ......................................... 57

23

Section 2 : interfaces fondes sur les


listes et sur Navigateur .................................. 61

25

Section 3 : applications non fondes


sur des listes .................................................. 64
Section 4 : applications dimmersion ............ 69

29
30

Section 5 : crer et utiliser des


transformations CSS personnalises ............. 71

iPhone Livre Page VI Vendredi, 30. octobre 2009 12:04 12

VI

Dveloppez des applications pour liPhone

Section 6 : crer et utiliser un module


de glisser-dposer, de redimensionnement
et de rotation ................................................. 78
En rsum ..................................................... 89
4. GPS, acclromtre et autres fonctions
natives avec QuickConnectiPhone .............
Section 1 : activation de lappareil
en JavaScript .................................................
Section 2 : activation de lappareil
en Objective-C ..............................................
Section 3 : implmentation Objective-C de
larchitecture de QuickConnectiPhone .........
En rsum .....................................................
5. GPS, acclromtre et autres fonctions
natives avec PhoneGap ...............................
Section 1 : activation de lappareil
en JavaScript .................................................
Section 2 : activation de lappareil
en Objective-C ..............................................
En rsum .....................................................
6. Cartes Google ...............................................
Section 1 : afficher une carte dans une
application JavaScript QuickConnect ...........
Section 2 : implmentation Objective-C
du module de cartographie
de QuickConnect ...........................................
En rsum .....................................................

91

Section 2 : utilisation des bases de donnes


SQLite avec WebView ................................... 153
Section 3 : utilisation de bases de donnes
SQLite natives ............................................... 158
Section 4 : utilisation de DataAccessObject
avec les bases de donnes du moteur
WebKit ........................................................... 161

92

Section 5 : utilisation de DataAccessObject


avec les bases de donnes natives .................. 172

98

En rsum ...................................................... 182


8. Donnes distantes ......................................... 185

107
113

Section 1 : application
browserAJAXAccess ..................................... 186

115

Section 2 : utilisation
de ServerAccessObject .................................. 188
Section 3 : ServerAccessObject ..................... 193

115

Section 4 : fonctions de contrle


de la scurit .................................................. 203

122
130

En rsum ...................................................... 204

133
133

138
149

7. Bases de donnes ......................................... 151


Section 1 : application BrowserDBAccess ... 151

A. Introduction JSON ................................... 205


Section 1 : les fondamentaux ......................... 205
Section 2 : une API JavaScript pour JSON .... 208
En rsum ...................................................... 211
B. Plan de dveloppement
pour QuickConnectFamily ........................ 213
C. Plan de dveloppement
pour PhoneGap .......................................... 219
Index .................................................................. 223

iPhone Livre Page 1 Vendredi, 30. octobre 2009 12:04 12

Prface

Cet ouvrage explique comment crer un nouveau type dapplications pour liPhone : les
applications hybrides crites en HTML, CSS et JavaScript. Ce sont des applications autonomes qui sexcutent sur liPhone comme des applications normales, mais sans que les
fichiers requis rsident sur un serveur Internet.
La cration dapplications hybrides pour liPhone permet de rduire le temps de dveloppement et dapprentissage, car il nest plus ncessaire de se former Objective-C ou de
matriser les frameworks Cocoa.

Outils pour le dveloppement dapplications


hybrides
Dans ce livre, nous tudierons les deux paquetages logiciels JavaScript open-source les
plus utiliss dans le dveloppement dapplications pour liPhone et liPod Touch : QuickConnectiPhone et PhoneGap. Ils permettent de construire des applications JavaScript qui
accdent aux fonctionnalits natives de lappareil, comme le vibreur, les informations de localisation GPS, lacclromtre, etc., sans crire une seule ligne de code Objective-C ou Cocoa.
QuickConnectiPhone (http://quickconnect.pbwiki.com) expose le fonctionnement natif
de lappareil et propose un framework complet de haut niveau pour le dveloppement.
Il rduit normment le temps de mise sur le march dune application, car le code glue
quil faut normalement crire en Objective-C, Cocoa et JavaScript est fourni par le
framework. Mieux encore, aucun serveur distant nest requis pour hberger les fichiers
JavaScript, HTML et CSS.

iPhone Livre Page 2 Vendredi, 30. octobre 2009 12:04 12

Dveloppez des applications pour liPhone

Le second paquetage, PhoneGap (http://phonegap.com), expose un nombre moindre de


comportements natifs et se prsente sous la forme dune bibliothque, non dun framework
complet. En tant que bibliothque, PhoneGap vous permet de construire lapplication
votre manire. En revanche, un serveur distant est obligatoire pour hberger les fichiers 1.
De manire faciliter lapprentissage et la comprhension, les exemples dcrits tout au
long de cet ouvrage sont intressants et importants.
Si votre objectif est de crer des applications installables, si vous avez les connaissances
web requises et si vous souhaitez proposer des solutions dynamiques et convaincantes qui
seront rellement utilises, ce livre vous expliquera comment ces deux paquetages peuvent
rpondre vos besoins.
Le Tableau P.1 compare les possibilits de chaque paquetage au moment de lcriture de
ces lignes.
Tableau P.1 : Comparaison des possibilits de QuickConnectiPhone et de PhoneGap

Fonctionnalits

QuickConnectiPhone

PhoneGap

GPS

Oui

Oui

Acclromtre

Oui

Oui

Vibreur

Oui

Oui

Sons systme

Oui

Oui

Rseau ad hoc (Bonjour)

Oui

Non

Rseau par cble de synchronisation

Oui

Non

Accs une base de donnes par le navigateur

Oui

Non

Accs une base de donnes intgre

Oui

Non

Bibliothque de glisser-dposer

Oui

Non

Enveloppe AJAX

Oui

Non

Enregistrement/lecture de fichiers audio

Oui

Non

Cartes Google embarques

Oui

Non

Bibliothque pour tableaux et graphiques

Oui

Non

1. N.d.T. : partir de la version 0.7.3, PhoneGap enregistre les fichiers JavaScript, HTML et CSS sur
lappareil, non plus sur un serveur web.

iPhone Livre Page 3 Vendredi, 30. octobre 2009 12:04 12

Prface

Comment utiliser ce livre


Chaque chapitre est organis en deux parties. La premire explique comment utiliser la
fonctionnalit de QuickConnectiPhone ou de PhoneGap qui permet de raliser une tche
particulire, par exemple obtenir la golocalisation de lappareil. La seconde partie
prsente le code qui se cache derrire lappel JavaScript utilis, ainsi que son fonctionnement. Vous pouvez ainsi dcider du niveau de dtails du code JavaScript et Objective-C
jusquo vous irez.

Le Chapitre 1, "Dvelopper avec Dashcode et Xcode", explique comment utiliser


Dashcode et Xcode avec QuickConnectiPhone et PhoneGap pour crer rapidement des
applications amusantes pour liPhone. Il fournit les bases de lutilisation de Dashcode
et montre comment dplacer votre application Dashcode dans Xcode pour sa compilation
et son excution sur des appareils.

Le Chapitre 2, "Modularit JavaScript", montre comment rduire normment le temps


de mise sur le march dune application en exploitant la modularit du framework
QuickConnectiPhone. Il explique comment exploiter les contrleurs frontaux, les
contrleurs dapplication et la rflexion JavaScript.

Le Chapitre 3, "Interfaces utilisateur", facilite lacceptation de vos applications par


lApp Store dApple. Il dcrit les meilleures pratiques du dveloppement dapplications fonctionnelles pour liPhone. Les diffrents types dapplications gnralement
cres pour liPhone sont examins, ainsi que les piges viter.

Le Chapitre 4, "GPS, acclromtre et autres fonctions natives avec QuickConnectiPhone", montre comment obtenir des informations du GPS, de lacclromtre et de
lappareil. Il explique galement comment dclencher le vibreur, et lire et enregistrer
des fichiers audio. Le framework QuickConnectiPhone est utilis pour accder ces
fonctions de lappareil et pour les employer. Toutes ces possibilits ajoutent vos
applications un ct plaisant.

Le Chapitre 5, "GPS, acclromtre et autres fonctions natives avec PhoneGap",


montre comment obtenir des informations du GPS, de lacclromtre et de lappareil.
Il explique galement comment dclencher le vibreur, et lire et enregistrer des
fichiers audio. La bibliothque PhoneGap est utilise pour accder ces fonctions de
lappareil et pour les employer. Toutes ces possibilits ajoutent vos applications un
ct plaisant.

Le Chapitre 6, "Cartes Google", dcrit lintgration dune carte Google une application en utilisant QuickConnectiPhone. Il sagit de lune des fonctionnalits les plus
demandes, qui vite aux utilisateurs de passer par lapplication de cartographie !

iPhone Livre Page 4 Vendredi, 30. octobre 2009 12:04 12

Dveloppez des applications pour liPhone

Le Chapitre 7, "Bases de donnes", explique comment lire et enregistrer des donnes


dans des bases SQLite intgres lapplication dveloppe avec le framework QuickConnectiPhone. Si vous devez accompagner votre nouvelle application dune base de
donnes contenant un jeu de donnes prdfini, lisez ce chapitre.

Le Chapitre 8, "Donnes distantes", montre comment accder facilement des


donnes disponibles sur des serveurs et/ou des services distants depuis votre application en utilisant une enveloppe qui permet dextraire des informations depuis
nimporte quel lieu. Par exemple, vous pouvez rcuprer des donnes partir dun blog
et les fusionner dans un flux Twitter. Grce au module daccs aux donnes distantes
de QuickConnectiPhone, rien nest plus facile.

Ce livre comprend galement trois annexes :

LAnnexe A, "Introduction JSON", est une courte introduction JSON (JavaScript


Object Notation). Ce format est trs utilis et constitue la solution la plus simple pour
envoyer des donnes leurs destinataires.

LAnnexe B, "Plan de dveloppement pour QuickConnectFamily", prsente le futur de


QuickConnectiPhone. Si vous prvoyez de dvelopper des applications pour liPhone
et dautres plates-formes, comme les tlphones Android de Google, les tlphones de
Nokia, les Blackberry et les ordinateurs de bureau sous Mac OS X, Linux et Windows,
vous devez lire cette annexe.

LAnnexe C, "Plan de dveloppement pour PhoneGap", prsente le futur de PhoneGap. Si vous envisagez de crer des applications pour liPhone et dautres platesformes, comme les tlphones Android de Google, les tlphones de Nokia, les Blackberry et les ordinateurs de bureau sous Mac OS X, Linux et Windows, vous devez
lire cette annexe.

Code des exemples


Les fichiers des exemples de code sont disponibles depuis le site web Pearson (http://
www.pearson.fr), en suivant le lien Codes sources sur la page ddie ce livre. Les
dernires versions de ces exemples, en anglais, sont fournies dans le paquetage de QuickConnectiPhone et dans le modle dapplication PhoneGap. Dans cet ouvrage, les commentaires ont t traduits afin de faciliter la lecture, mais certains seront invitablement en
anglais car gnrs par les frameworks.

iPhone Livre Page 5 Vendredi, 30. octobre 2009 12:04 12

Prface

Ressources en ligne
Le dveloppement de QuickConnectiPhone et de PhoneGap est en cours et les volutions
sont rapides. Pour connatre les nouvelles fonctions et les nouvelles possibilits, et pour en
savoir plus, consultez les liens suivants.

QuickConnectiPhone

tlchargement du framework et de plusieurs exemples (http://sourceforge.net/


projects/quickconnect/) ;

blog concernant le dveloppement (http://tetontech.wordpress.com) ;

wiki ddi au framework (http://quickconnect.pbwiki.com/FrontPage) ;

groupe Google (http://groups.google.com/group/quickconnectiPhone/) ;

service Twitter (http://twitter.com/quickconnect).

PhoneGap

tlchargement du framework et de plusieurs exemples (http://sourceforge.net/


projects/phonegapinstall/) ;

site web de la bibliothque (http://www.phonegap.com/) ;

wiki ddi la bibliothque (http://phonegap.pbwiki.com/) ;

groupe Google (http://groups.google.com/group/phonegap) ;

service Twitter (http://twitter.com/phonegap).

Prrequis
Pour rellement profiter du contenu de cet ouvrage, vous devez possder des connaissances
de base en HTML, CSS et JavaScript. Si vous avez dj cr des pages web laide de
ces technologies, vous tes prt crer des applications pour liPhone. Si vous avez besoin
daide avec Objective-C, que ce soit pour QuickConnectiPhone ou PhoneGap, elle vous
sera fournie. Ce livre ne constitue pas une introduction Objective-C ni son utilisation
dans le dveloppement dapplications pour liPhone.
Vous devez tlcharger et installer les outils Xcode dApple disponibles sur le site web
du dveloppeur pour liPhone (http://developer.apple.com/iphone). Ils ncessitent
Mac OS X 10.5 ou ultrieur et une machine Intel.

iPhone Livre Page 6 Vendredi, 30. octobre 2009 12:04 12

Dveloppez des applications pour liPhone

Bien que cela ne soit pas obligatoire, il est prfrable de disposer dun iPhone ou dun
iPod Touch afin de tester et dexcuter les applications sur ces appareils.

Remerciements
Je souhaite remercier tout particulirement Daniel Barney pour avoir travaill sur le code
dintgration des cartes Google. Merci galement mes collgues du dpartement des
technologies de linformation de luniversit Brigham Young, Idaho, pour leur attention et
leurs suggestions.

propos de lauteur
Lee S. Barney (Rexburg, Idaho) est professeur dans le dpartement des technologies de
linformation au Business and Communication College de luniversit Brigham Young,
dans lIdaho. Il a travaill comme directeur des technologies de linformation pour
@HomeSoftware, une socit qui dveloppe des applications web mobiles de planification
pour le march des soins mdicaux domicile. Avant cela, il a t pendant plus de sept ans
programmeur, ingnieur logiciel senior, directeur du service de la fiabilit des chefs de
projet pour AutoSimulations, Inc., le principal fournisseur de logiciels de planification
pour lindustrie des semi-conducteurs. Il est lauteur du livre Oracle Database AJAX &
PHP Web Application Development.

Contacter lauteur
Pour contacter lauteur par courrier lectronique, utilisez ladresse quickconnectfamily@gmail.com. Pour dautres mthodes de contact, utilisez les liens Twitter, wiki et
groupe Google donns prcdemment.

iPhone Livre Page 7 Vendredi, 30. octobre 2009 12:04 12

1
Dvelopper avec Dashcode
et Xcode
Utiliss ensemble, Dashcode et Xcode offrent la puissance et la simplicit dutilisation
ncessaires la cration dapplications hybrides uniques et passionnantes pour liPhone.
Puisque ces deux outils fournissent des modles personnaliss adapts aux applications
hybrides pour liPhone, vous navez pas besoin de crer votre propre enveloppe en Objective-C. Les trois premires sections de ce chapitre expliquent comment utiliser les
modles dapplication existants pour Dashcode et Xcode. Grce ces modles, vous
pouvez crer rapidement des applications hybrides pour liPhone. Les quatre dernires
sections introduisent les bases dObjective-C et la manire de structurer une application
iPhone en Objective-C dans les deux outils les plus employs QuickConnectiPhone et
PhoneGap.

iPhone Livre Page 8 Vendredi, 30. octobre 2009 12:04 12

Dveloppez des applications pour liPhone

Section 1 : utiliser Dashcode et le modle


QuickConnect
Dans les applications hybrides pour liPhone, une grande partie de linterface utilisateur et
des interactions est cre avec HTML, JavaScript et CSS. Par consquent, le dveloppement et le dbogage se font principalement dans Dashcode. Les possibilits et la facilit
demploi de loutil de construction dinterfaces par glisser-dposer fourni par Dashcode sont
uniques. Dashcode est utilis pour crer une grande partie de lapplication et sert galement
la tester en employant le simulateur diPhone et les outils de dbogage intgrs.
Puisque les applications hybrides pour liPhone ont beaucoup de code en commun, la
cration dun modle contenant ce code permet dviter son criture ou son importation
chaque dbut dun nouveau projet. Nous reviendrons sur ce code commun au Chapitre 2.
Pour tlcharger QuickConnectiPhone, allez sur la page http://sourceforge.net/projects/
quickconnect. Le paquetage obtenu inclut un modle Dashcode qui vous aidera crer
des applications hybrides pour liPhone. Le programme dinstallation de QuickConnectFamily ajoute ce modle Dashcode. Malheureusement, au moment de lcriture de ces
lignes, les auteurs de PhoneGap ne proposent pas de modle Dashcode.
Aprs avoir excut le programme dinstallation de QuickConnectFamily et avoir lanc
Dashcode, le modle QuickConnectiPhone est propos la fin de la liste affiche dans la
rubrique Dashboard Widget. En double-cliquant sur licne QuickConnectiPhone, vous
arrivez directement lcran principal de Dashcode, avec une interface utilisateur vierge
(voir Figure 1.1).
Pour comprendre les fichiers inclus dans le framework et les utiliser facilement, nous
allons crer une premire interface utilisateur simple avec Dashcode et la dployer sur
liPhone avec Xcode. Elle sera constitue uniquement dun bouton et dune zone de texte.
Lors dun clic sur le bouton, la zone de texte affichera : "Vous lavez fait !"

Applications hybrides et bote dalerte


Les dveloppeurs qui ont lhabitude de coder en JavaScript utilisent souvent une bote
dalerte pour dboguer lapplication ou afficher des messages lutilisateur. La fonction
JavaScript alert est en ralit un appel du code natif dans le navigateur, non une possibilit du moteur JavaScript.
Ce fonctionnement nest pas mis en uvre dans les applications QuickConnectiPhone car
lutilisation des botes de dialogue est contraire aux standards tablis par Apple pour
linterface utilisateur des applications iPhone. Pour le dbogage, vous pouvez vous servir
du dbogueur de Dashcode. Si vous dplacez votre application dans Xcode, vous pouvez
employer la fonction debug pour afficher des messages dans la console de Xcode.

iPhone Livre Page 9 Vendredi, 30. octobre 2009 12:04 12

Chapitre 1

Dvelopper avec Dashcode et Xcode

PhoneGap propose une bote dalerte, mais pas la fonction de dbogage de Xcode.
Pour afficher des informations importantes, ajoutez-les dans un lment HTML <div>, ou
autre, quel que soit loutil que vous utilisez.
Noubliez pas : vous devez tre attentif, sans tre alarmiste.

Figure 1.1
Le modle QuickConnectiPhone est utilis dans Dashcode. Le contenu de la bibliothque standard
est affich.

Avant de crer linterface utilisateur, vrifiez que la fentre Bibliothque est ouverte.
Ensuite, recherchez llment Texte dans la bibliothque des parties et faites-le glisser sur
lcran vierge de lapplication. Une nouvelle zone de texte, contenant le mot "Texte",
saffiche en haut de linterface. Par dfaut, la taille de cette zone de texte est fixe 100 %.
Dashcode a insr dynamiquement une balise HTML <div> dans le fichier index.html de
lapplication, ainsi que du code JavaScript pour la complter par le texte, la couleur
darrire-plan et les autres caractristiques que vous choisissez.
Pour notre exemple, nous souhaitons fixer lidentifiant de la balise de texte display et
effacer son contenu. Pour cela, nous allons employer linspecteur des lments de linterface.

iPhone Livre Page 10 Vendredi, 30. octobre 2009 12:04 12

10

Dveloppez des applications pour liPhone

Cliquez sur licne Inspecteur dans la barre suprieure de Dashcode de manire activer
la bote de dialogue correspondante. Slectionnez longlet Attributs (de couleur rouge et
blanc) dans le coin suprieur gauche de linspecteur, fixez le champ Identifiant
display et effacez le contenu du champ tiquette.
Ajoutez un bouton poussoir linterface, en faisant glisser et en dposant la partie correspondante sous la zone de texte. Linspecteur affiche prsent les informations concernant
ce bouton, non plus celles du champ de texte. Ouvrez longlet Comportements en
cliquant sur le cube bleu dans le coin suprieur droit de linspecteur. Il permet de dfinir
les fonctions JavaScript qui serviront de gestionnaires pour les types dvnements
lists. Vous remarquerez que plusieurs des vnements standard de la souris sont absents.
Ils ont t remplacs par ongesturestart, ongesturechange et ongestureend. Saisissez
changeText dans la colonne Gestionnaires de lvnement onclick. Cette opration
ajoute une fonction changeText dans le fichier main.js et affiche son contenu lcran
afin que vous puissiez saisir le code excut lorsque lvnement onclick est dclench.
Pour notre exemple simple, placez le code suivant dans la fonction changeText :
document.getElementById(display).innerHTML = "Vous lavez fait!";

Notre application peut prsent tre excute dans le simulateur diPhone 1. Cliquez sur
licne Excuter dans le coin suprieur gauche de Dashcode. Le simulateur est alors
dmarr et lapplication y est excute (voir Figure 1.2).
Puisque lapplication est dbogue et termine, vous pouvez dplacer le code dans Xcode
en vue de son dploiement sous forme dune application installable.
Tout dabord, vous devez utiliser Dashcode pour dployer lapplication actuelle. En effet,
le code est cach dans le projet Dashcode et contient des directives que seul Dashcode
peut comprendre. Cliquez sur licne Partager dans la partie gauche de Dashcode afin
dafficher lcran de dploiement. Vous pourrez ainsi enregistrer lintgralit des fichiers
HTML, CSS et JavaScript sur le disque de manire les inclure dans votre application.
Dans le champ Chemin, saisissez un nom pour le nouveau rpertoire dans lequel seront
placs ces fichiers. Ils peuvent prsent tre imports dans Xcode. La Figure 1.3 montre
lcran de dploiement.
Pour de plus amples informations concernant les fichiers JavaScript inclus dans ce modle
et leur utilisation pour simplifier la cration dune application, consultez le Chapitre 2.

1. N.d.T. : par dfaut, le simulateur diPhone est normalement configur pour la langue anglaise. Pour le
passer en franais, utilisez lapplication Rglages.

iPhone Livre Page 11 Vendredi, 30. octobre 2009 12:04 12

Chapitre 1

Dvelopper avec Dashcode et Xcode

Figure 1.2
Lapplication en cours
dexcution dans le
simulateur diPhone
de Dashcode.

Figure 1.3
Lcran de dploiement affiche lapplication termine en cours de dploiement vers le rpertoire
Exemple1_Chapitre1.

11

iPhone Livre Page 12 Vendredi, 30. octobre 2009 12:04 12

12

Dveloppez des applications pour liPhone

Section 2 : utiliser Xcode et le modle QuickConnect


Puisque vous avez excut le programme dinstallation de QuickConnectFamily, le
modle Xcode pour les applications QuickConnectiPhone a t install. Nous allons
lutiliser pour crer le projet Xcode de notre application hybride QuickConnectiPhone.
Cette section dcrit les diffrentes tapes de la procdure. Le wiki QuickConnectFamily
propose une vido qui dcrit cette procdure (http://quickconnect.pbwiki.com/MovingDashcode-projects-to-Xcode).
Commencez par slectionner File > NewProject, puis iPhone OS > Applications.
Double-cliquez sur licne QuickConnect iPhone Application et nommez le projet
(le rpertoire correspondant est cr sur le disque dur). Xcode cre un projet qui
comprend les fichiers Objective-C ncessaires lexcution de lapplication JavaScript
directement sur lappareil, sans disposer dun accs rseau ou dun accs Internet. Dans le
groupe Resources de lapplication, vous trouverez un ensemble de fichiers HTML, CSS
et JavaScript.
Lun de ces fichiers se nomme index.html. Il contient tout le code HTML, CSS et JavaScript dun exemple dapplication prte fonctionner. La Figure 1.4 montre lexcution de
cet exemple sur le simulateur sous forme dune application installe. Avant de lessayer,
vous devez prciser Xcode dutiliser le simulateur de liPhone. Pour cela, ouvrez le
menu Project > Set Active SDK, puis choisissez un simulateur dans la liste.
Figure 1.4
Lapplication
QuickConnect par dfaut.

iPhone Livre Page 13 Vendredi, 30. octobre 2009 12:04 12

Chapitre 1

Dvelopper avec Dashcode et Xcode

13

Pour inclure dans ce projet les fichiers crs prcdemment dans Dashcode, commencez
par supprimer les fichiers suivants partir du groupe Resources :

index.html ;

main.css ;

main.js ;

les ventuels fichiers du sous-groupe Parts ;

les ventuels fichiers du sous-groupe Images.

Ensuite, importez les fichiers index.html, main.css et main.js de lexemple prcdent. Pour
cela, maintenez enfonce la touche Contrle et cliquez du bouton droit sur le groupe
Resources, puis slectionnez Add > Existing Files. Allez dans le rpertoire dans
lequel vous avez dploy lapplication Dashcode et slectionnez index.html, main.css et
main.js. Vous pouvez copier les fichiers dans le projet Xcode ou les utiliser partir de leur
emplacement actuel. Pour cet exemple, cochez la case Copy items into destination
groups folder (if needed).

Copier ou ne pas copier, telle est la question


Cest vous de dcider si vous devez copier les fichiers existants ou laisser Xcode utiliser
des rfrences vers ces fichiers. Comment prendre votre dcision ? Chaque mthode
prsente des avantages.
Si vous copiez les fichiers, le rpertoire du projet est complet et peut tre pass dautres
dveloppeurs sans quils aient besoin de reproduire la structure de rpertoires de la
machine do proviennent les fichiers dorigine.
Avec les rfrences, vous pouvez retourner dans Dashcode pour apporter des modifications et exporter ensuite le projet de manire actualiser les fichiers. Vous navez pas
besoin de les importer nouveau dans Xcode.

Cliquez ensuite du bouton droit sur le groupe Parts (sil nexiste pas sur le disque dur, il
est affich en rouge et vous devrez le crer avant limportation) et importez les fichiers qui
se trouvent dans le dossier Parts. Rptez cette opration pour le groupe Images et le
dossier Images. Lapplication est quasiment prte tre excute.
Puisque des fichiers ont t ajouts au groupe Resources, il faut indiquer Xcode quil
doit les inclure dans les ressources de lapplication. Ouvrez la rubrique Targets, puis
dveloppez votre application et Copy Bundle Resources. Vous voyez alors les fichiers de
ressources requis par lapplication. Slectionnez les fichiers, non les groupes, que vous

iPhone Livre Page 14 Vendredi, 30. octobre 2009 12:04 12

14

Dveloppez des applications pour liPhone

venez dajouter dans votre projet et faites-les glisser dans la liste Copy Bundle Resources.
Ensuite, dveloppez la rubrique Compile Sources et supprimez tous les fichiers JavaScript, car ils ne pourront videmment pas tre compils. Pour cela, maintenez enfonce la
touche Ctrl, cliquez du bouton droit sur chacun deux et slectionnez Delete. Les fichiers
sont supprims de la liste des fichiers compiler, mais ils ne sont pas retirs du projet ou
du disque.
Puisque Dashcode utilise des rpertoires et que Xcode utilise des groupes, vous devez
apporter deux autres modifications avant de pouvoir excuter lapplication. La premire
concerne la section <head> du fichier index.html. Puisque les fichiers JavaScript et les
autres fichiers rfrencs sont placs dans le rpertoire des ressources de lapplication
finale, les rfrences aux rpertoires Parts et QCiPhone doivent tre supprimes. Par
exemple, avant la suppression des rfrences, voici laspect dune balise <script> :
<script type="text/JavaScript" src="Parts/utilities.js" charset="utf-8"></script>

Elle doit devenir la suivante :


<script type="text/JavaScript" src="utilities.js" charset="utf-8"></script>

Puisque des images sont utilises pour les boutons et autres lments crs dans Dashcode, vous devez galement retrouver les instances de la chane Images/ dans lensemble
du projet et les remplacer par une chane vide. Cette opration est trs facile en ouvrant le
menu Edit, en choisissant Find > Find in Project et en recherchant Images/. La
Figure 1.5 montre les rsultats de la recherche dans notre exemple, avant la modification
du fichier PushButton.js.
Vous pouvez prsent installer et excuter votre application en slectionnant licne
Build and Go, qui se trouve dans la barre suprieure de lapplication Xcode. Si vous recevez le message derreur "No provisioned iPhone OS device is connected", vous pouvez
installer et excuter lapplication dans le simulateur la place de votre appareil. Pour
cela, cliquez sur Succeeded dans le coin infrieur droit de la fentre Xcode, ouvrez la
liste Device | Debug et slectionnez une version du simulateur. Notez que vous
pouvez galement choisir Release ou Debug dans cette liste droulante. Cette bote de
dialogue est frquemment utilise au cours des dveloppements pour effectuer ce type de
modification. La Figure 1.6 montre lapplication installe et en cours dexcution dans le
simulateur.
Flicitations, vous venez de terminer votre premire application hybride pour liPhone.

iPhone Livre Page 15 Vendredi, 30. octobre 2009 12:04 12

Chapitre 1

Dvelopper avec Dashcode et Xcode

15

Figure 1.5
Lcran de recherche montre les rsultats de la recherche de la chane Images/ sur lensemble du projet.

Figure 1.6
Lapplication
Exemple2_Chapitre1 est
installe et sexcute sur
le simulateur diPhone.

iPhone Livre Page 16 Vendredi, 30. octobre 2009 12:04 12

16

Dveloppez des applications pour liPhone

Approvisionnement
Lapprovisionnement (provisioning) est un processus en plusieurs tapes que vous, ou
votre reprsentant, devez excuter pour que vous puissiez installer et excuter votre
application sur un iPhone.
Pour prparer votre iPhone, vous devez tre membre de lADC (Apple Developer Connection) et tre abonn au Program Portal. Si vous faites partie dune quipe, lapprovisionnement a sans doute dj t effectu pour vous. Dans ce cas, il vous suffit simplement
denvoyer les informations dapprovisionnement votre iPhone.
Le site ADC dtaille la procdure dapprovisionnement. Assurez-vous de raliser toutes les
tapes indiques car toute erreur risque de se solder par un chec qui vous empchera de
tester vos applications sur votre appareil.

Section 3 : les bases dObjective-C


Cette section ne constitue pas un didacticiel dtaill sur Objective-C, pas plus quune
prsentation complte sur la manire demployer ce langage pour dvelopper des applications pour liPhone. Elle se contente dexpliquer comment les classes Objective-C utilises
dans des modles interagissent et se comportent, afin que vous puissiez exploiter ces informations dans les applications hybrides pour liPhone. Elle suppose que vous ayez une
certaine connaissance des objets, mthodes et attributs. Si vous souhaitez en savoir plus
sur le framework JavaScript ou si vous ntes pas intress par le code Objective-C, vous
pouvez sauter la suite de ce chapitre et aller directement au Chapitre 2. Pour de plus
amples informations concernant le dveloppement en Objective-C pour liPhone, consultez louvrage The iPhone Developers Cookbook: Building Applications with the iPhone SDK,
dErica Sadun.
Objective-C est un langage intressant. Les personnes qui possdent une exprience dans
dautres langages, comme JavaScript, PHP, Java ou Perl, risquent de le trouver intimidant
et incomprhensible au premier abord. Toutefois, il mrite dtre tudi de plus prs et pas
uniquement parce quil sagit du langage "natif" de liPhone.
Objective-C est une variante oriente objet de C. Vous pouvez employer tous les aspects
puissants mais dangereux de la programmation en C/C++, comme larithmtique de pointeurs, et bnficier de mcanismes qui facilitent le travail, comme la gestion automatique
de la mmoire. Dans un langage orient objet, la manire dinstancier un objet est la
premire chose connatre. Si une classe nomme Mammifere est disponible dans le code

iPhone Livre Page 17 Vendredi, 30. octobre 2009 12:04 12

Chapitre 1

Dvelopper avec Dashcode et Xcode

17

source et si elle possde deux attributs, couleurPoils et tauxButyreux, il est possible de


linstancier en JavaScript de la manire suivante :
var unMammifere = new Mammifere("brun", 0.15);

Vous pourriez penser que cette mthode est normale et attendre des autres langages un
comportement semblable. Dans ce cas, vous risquez de trouver trange linstanciation des
objets en Objective-C. Voici linstanciation quivalant la prcdente en Objective-C :
Mammifere *unMammifere = [[Mammifere alloc] initAvecCouleur: @"brun" etTauxBuryteux:
0.15];

Certaines parties sont comprhensibles, dautres, beaucoup moins. Si vous y rflchissez,


alloc a un sens car cest ainsi que de lespace en mmoire RAM est allou lobjet
Mammifere. Mme initAvecCouleur et etTauxBuryteux ont un sens en tant que mutateurs ou passeurs des deux paramtres requis. Toutefois, que se passe-t-il rellement et que
signifient les crochets ?
Pour toutes les interactions avec les objets et les autres lments qui ne sont pas ncessairement des objets dans dautres langages, Objective-C utilise le passage de messages.
tudions le code suivant :
[Mammifere alloc]

Prcdemment, nous avons suppos que ce fragment de code allouait de lespace en RAM
pour un objet de type Mammifere. Cest effectivement le cas. Les crochets autour de
Mammifere et dalloc indiquent que lobjet applicatif qui reprsente la classe Mammifere
reoit le message alloc. Autrement dit, ce bout de code doit se lire "passer un message
alloc lobjet de classe Mammifere". Le passage du message alloc lobjet de classe
Mammifere conduit au retour dun pointeur sur un nouvel objet Mammifere.

Pointeurs
Les pointeurs sont intressants. Toutefois, de nombreux dveloppeurs en ont peur car ils
ne les comprennent pas ou ne les connaissent pas.
Pour mieux les expliquer, prenons lanalogie suivante. Imaginez une foule immense dans
laquelle se trouvent Anne et Jean. Ces deux personnes se connaissent et Anne sait o Jean
se trouve dans la foule. Vous abordez Anne et lui demandez o est Jean. Anne pointe son
doigt vers Jean et rpond "le voici".
ce moment-l, Anne est un pointeur sur Jean. Si vous considrez un pointeur comme
quelque chose qui sait o un objet se trouve en mmoire, vous avez tout compris.

iPhone Livre Page 18 Vendredi, 30. octobre 2009 12:04 12

18

Dveloppez des applications pour liPhone

Ce nouvel objet Mammifere instanci peut recevoir des messages. Lextrait de code prcdent
contient un autre message pour ce nouvel objet Mammifere.
Ce nouveau message combine initAvecCouleur et etTauxBuryteux. Nous savons que
ces deux parties reprsentent un message car elles sont, avec le nouvel objet Mammifere,
entoures de crochets qui, rappelons-le, signifient un passage de message. Les multiples
parties dun message sont spares par des espaces.
Par ailleurs, les diffrentes parties du message et les valeurs correspondantes sont lies par
le caractre deux-points (:). Un seul paramtre peut tre associ chaque partie du
message. Le message pass retourne un pointeur sur le nouvel objet Mammifere allou afin
quil puisse tre enregistr localement en vue de son utilisation ultrieure. En Objective-C,
ces indicateurs de messages, quil sagisse dun message une ou plusieurs parties, sont
appels slecteurs car ils dsignent les mthodes de lobjet slectionnes par le compilateur
et excutes.
Revenez au projet Xcode Exemple2_Chapitre1 cr la Section 2. Dans le fichier
Exemple2_Chapitre1AppDelegate.m, examinez la mthode applicationDidFinishLaunching gnre par le modle. Ne vous occupez pas du fonctionnement du code,
simplement du passage de message :
1 - (void)applicationDidFinishLaunching:(UIApplication *)application {
2
// Cette ligne aide au dbogage. Vous pouvez voir exactement o sont places
vos vues.
3
// Si vous voyez du rouge, la fentre est vide. Sinon, utilisez le noir.
4
//window.backgroundColor = [UIColor redColor];
5
6
7
QuickConnectViewController *aBrowserViewController=
[[QuickConnectViewController alloc] init];
8
9
// Ajouter la vue CreateViewController window en tant que vue secondaire.
10
[window addSubview:aBrowserViewController.view];
11
12
[window makeKeyAndVisible];
13 }

La ligne 7 doit vous sembler familire. Elle nimplique aucun mammifre, mais elle utilise
les messages alloc et init que vous avez rencontrs prcdemment. Dans ce cas, un
objet QuickConnectViewController est allou et initialis. Son objet de classe reoit le
message alloc et retourne un pointeur sur le nouvel objet QuickConnectViewController
allou. Celui-ci, au travers de son pointeur, reoit le message init.
Ce message ralise une opration semblable celle du message multipartie initAvecCouleur:etTauxBuryteux de Mammifere, mais il est beaucoup plus simple. Il sagit dun

iPhone Livre Page 19 Vendredi, 30. octobre 2009 12:04 12

Chapitre 1

Dvelopper avec Dashcode et Xcode

19

message en une partie, sans aucun paramtre. Plus loin dans ce chapitre, vous verrez
comment crer des mthodes dinitialisation et dautres mthodes excutes par les objets
lorsquils recevront un message.
La ligne 10 envoie un message window. Ce message addSubView possde un paramtre
qui correspond lattribut view contenu dans lobjet aBrowserViewController.
Vous savez prsent comment instancier un objet, enregistrer localement un pointeur sur
le nouvel objet, comment accder aux attributs dun objet et comment passer aux objets
des messages avec ou sans paramtre. Vous disposez donc des bases dObjective-C ncessaires pour comprendre le code des modles QuickConnectiPhone et PhoneGap. Nous
allons prsent voir comment les applications Objective-C sont assembles.

Section 4 : structure Objective-C dune application


QuickConnectiPhone
Bien que cette section prsente du code issu du modle dapplication QuickConnectiPhone, une approche quivalente est employe par PhoneGap et toutes les autres mises en
uvre des applications hybrides. Vous pouvez utiliser lune de ces implmentations ou, en
les tudiant, crer votre propre version.
Imaginez que vous disposiez dun grand nombre de parts dans une entreprise prospre.
Imaginez quune runion des actionnaires ait lieu pour lire le prsident du conseil
dadministration, mais que vous ne puissiez pas y participer en raison de vos vacances
Tahiti. Comment pouvez-vous nanmoins voter ?
Si vous donnez pouvoir une autre personne pour voter votre place, elle devient votre
mandataire. En tant que mandataire, elle est pleinement autorise agir pour votre compte
lors de la runion. Votre mandataire peut donc tre appel votre dlgu. Ce dlgu vous
considre comme le mandant car vous tes lactionnaire rel. La Figure 1.7 illustre ces
relations. Les applications Objective-C pour liPhone se fondent sur ces relations
mandant-dlgu entre des objets, dont lun reprsente le mandant et lautre, le dlgu.
Figure 1.7
Une reprsentation
graphique de la relation
mandant-dlgu.

Mandant

a un
a un

Mandataire/
dlgu

Les relations de type mandant-dlgu sont trs rpandues dans les applications Objective-C pour liPhone. Voici celles qui nous intressent principalement :

UIApplication/UIApplicationDelegate ;

iPhone Livre Page 20 Vendredi, 30. octobre 2009 12:04 12

20

Dveloppez des applications pour liPhone

UIWebView/UIWebViewDelegate ;

UIAccelerometer/UIAccelerometerDelegate.

ce stade, vous devez comprendre que limplmentation des mthodes du protocole pour
ces dlgus indique lapplication, la vue ou lacclromtre que vous souhaitez que
la prise en charge dvnements spcifiques se fasse par le dlgu la place de la
mthode. Chaque mthode du protocole est associe un vnement.

Protocoles
Un protocole est un ensemble de mthodes qui peuvent tre ajoutes une classe afin
quelle rponde certains messages.

En ayant ces concepts de mandant-dlgu lesprit, examinons une classe qui joue le rle
de dlgu. Le fichier den-tte de la classe Exemple2_Chapitre1AppDelegate a t
gnr par le modle QuickConnectiPhone lorsque que vous avez cr lapplication
Exemple2_Chapitre1 la Section 2. Il est donn ci-aprs.
Les fichiers den-tte Objective-C, ceux qui se terminent par .h, dclarent des classes.
Examinez celui de Exemple2_Chapitre1AppDelegate, mais sans vous occuper du fichier
dimplmentation :
1
2
3
4
5
6
7
8
9
10
11

// Exemple2_Chapitre1AppDelegate.h
#import <UIKit/UIKit.h>
#import "QuickConnectViewController.h"
@interface Exemple2_Chapitre1AppDelegate: NSObject <UIApplicationDelegate> {
IBOutlet UIWindow *window;
QuickConnectViewController *browserViewController;
}
@property (nonatomic, retain) UIWindow *window;
@property (nonatomic, retain) QuickConnectViewController *browser
ViewController;

12
13 @end

Examinez la ligne 5. Si vous connaissez Java, ne vous laissez pas induire en erreur par
lindicateur @interface. Il ne signifie pas que cette classe quivaille une interface Java.
Il signifie que ce fichier contient la dfinition de linterface de la classe. Ce fichier dentte dclare les attributs de la classe Exemple2_Chapitre1AppDelegate, la manire dy

iPhone Livre Page 21 Vendredi, 30. octobre 2009 12:04 12

Chapitre 1

Dvelopper avec Dashcode et Xcode

21

accder et les mthodes qui doivent tre mises en uvre dans le fichier dimplmentation.
Cette classe ne possde aucune mthode en propre.
Sil ne sagit pas dune dclaration dinterface la manire de Java, quel est donc le rle
de la ligne 5 ? Elle dclare le nom de la classe, Exemple2_Chapitre1AppDelegate, et
utilise le caractre deux-points pour indiquer quelle drive de la classe NSObject. La
classe est donc un NSObject et peut accepter tout message dfini par NSObject. Si vous
examinez la classe NSObject dans la documentation de lAPI (accessible au travers du
menu daide de Xcode), vous pouvez constater quelle possde une mthode description.
Par consquent, puisque Exemple2_Chapitre1AppDelegate hrite de NSObject, elle
possde galement une mthode description.
Aprs la dclaration dhritage de NSObject, vous voyez <UIApplicationDelegate>.
Cela indique la classe Exemple2_Chapitre1AppDelegate quelle se comporte comme
un dlgu de votre application et vous permet de mettre en uvre les mthodes des
messages du protocole UIApplicationDelegate dans le fichier dimplmentation de
Exemple2_Chapitre1AppDelegate. Lune des mthodes de ce protocole se nomme
applicationDidFinishLaunching.
Cette mthode est invoque lorsque le chargement de lapplication est termin et quelle
est prte tre excute. La mthode permet de personnaliser lapplication ou de demander
des informations supplmentaires lutilisateur.
Dans le code suivant, la ligne 13 contient la dfinition de applicationDidFinishLaunching donne par QuickConnectiPhone dans le fichier dimplmentation. Elle
commence par un signe moins (-) qui indique quil sagit dune mthode dobjet. (void)
signifie que la mthode ne retourne aucune valeur, tandis que :(UIApplication
*)application indique quelle attend un paramtre de type UIApplication.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

//
//
//
//

Exemple2_Chapitre1AppDelegate.m
Exemple2_Chapitre1

#import "Exemple2_Chapitre1AppDelegate.h"
@implementation Exemple2_Chapitre1AppDelegate
@synthesize window;
@synthesize browserViewController;

- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Cette ligne aide au dbogage. Vous pouvez voir exactement o sont places
vos vues.

iPhone Livre Page 22 Vendredi, 30. octobre 2009 12:04 12

22

Dveloppez des applications pour liPhone

15
16
17
18
19
20
21
22
23
24
25 }

// Si vous voyez du rouge, la fentre est vide. Sinon, utilisez le noir.


//window.backgroundColor = [UIColor redColor];

QuickConnectViewController *aBrowserViewController=
[[QuickConnectViewController alloc] init];
// Ajouter la vue CreateViewController window en tant que vue secondaire.
[window addSubview:aBrowserViewController.view];
[window makeKeyAndVisible];

Puisquelle fait partie de la classe dlgue de votre application, cette mthode applicationDidFinishLaunching est invoque automatiquement lorsque le chargement de
lapplication est termin. Cest pourquoi elle peut tre utilise pour instancier dautres
lments ncessaires lapplication. Dans cet exemple, vous pouvez voir la ligne 19
lallocation et linitialisation dune autre classe, QuickConnectViewController, ajoute
lapplication par le modle.
Les applications pour liPhone utilisent des vues, et nimporte quel objet UIWindow ou
UIView peut contenir des objets UIView. Par consquent, il est possible davoir des vues
imbriques. Cependant, cette conception est dconseille dans les applications pour
liPhone. la place de cette approche hirarchique, la plupart des dveloppeurs choisissent dchanger une vue secondaire par une autre un niveau aussi lev que possible,
selon les besoins de lutilisateur.
Le remplacement des vues secondaires rduit la complexit de la structure des vues de
lapplication. Par chance, le modle utilis pour crer lapplication a plac le nombre
de vues imbriques adquat pour que le contenu web puisse tre affich. En ralit,
comme nous le verrons plus loin, il a insr une vue secondaire web dans la vue qui a t
ajoute lobjet window.
Un attribut de la classe QuickConnectViewController correspond lobjet de vue qui
affiche le contenu dans la fentre de lapplication. Cet attribut doit tre ajout la fentre
principale en tant que vue secondaire, une opration effectue la ligne 22.
En plus de possder la vue du contenu, la classe QuickConnectViewController joue
galement le rle de dlgu pour la localisation GPS, lacclromtre, la vue web et
dautres types dvnements.

iPhone Livre Page 23 Vendredi, 30. octobre 2009 12:04 12

Chapitre 1

Dvelopper avec Dashcode et Xcode

23

Section 5 : structure Objective-C dune application


PhoneGap
En tant quapplications pour liPhone, les applications PhoneGap respectent galement
la mme structure mandant-dlgu que les applications QuickConnectiPhone (pour de
plus amples informations, consultez la Section 4). La classe dlgue que vous devez
comprendre se nomme GlassAppDelegate. Tout comme la classe Exemple2_Chapitre1AppDelegate examine la Section 4, elle possde un fichier de dfinition, GlassAppDelegate.h, et un fichier dimplmentation, GlassAppDelegate.m.
La classe GlassAppDelegate des applications PhoneGap nest pas seulement un dlgu
de lapplication, mais galement un dlgu pour tous les types de comportements. Les
fichiers .h et .m sont donc beaucoup plus complexes.
Dans le code suivant, vous constatez que la classe GlassAppDelegate est un dlgu pour
laffichage WebView, le gestionnaire de localisation GPS, lacclromtre et autres. En
effet, ces dlgus sont prsents sous forme dune liste dans la dclaration de linterface,
qui dbute la ligne 16.
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 <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <UIKit/UINavigationController.h>
#import
#import
#import
#import
#import

"Vibrate.h"
"Location.h"
"Device.h"
"Sound.h"
"Contacts.h"

@class GlassViewController;
@class Sound;
@class Contacts;
@interface GlassAppDelegate: NSObject <
UIApplicationDelegate,
UIWebViewDelegate,
CLLocationManagerDelegate,
UIAccelerometerDelegate,
UIImagePickerControllerDelegate,
UIPickerViewDelegate,
UINavigationControllerDelegate
>
{

iPhone Livre Page 24 Vendredi, 30. octobre 2009 12:04 12

24

Dveloppez des applications pour liPhone

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

IBOutlet
IBOutlet
IBOutlet
IBOutlet
IBOutlet

UIWindow *window;
GlassViewController *viewController;
UIWebView *webView;
UIImageView *imageView;
UIActivityIndicatorView *activityView;

CLLocationManager *locationManager;
CLLocation *lastKnownLocation;
UIImagePickerController *imagePickerController;
NSURLConnection *callBackConnection;
Sound *sound;
Contacts *contacts;
NSURL* appURL;
}
@property (nonatomic, retain)
@property (nonatomic, retain)
@property (nonatomic, retain)
@property (nonatomic, retain)
*imagePickerController;

CLLocation *lastKnownLocation;
UIWindow *window;
GlassViewController *viewController;
UIImagePickerController

- (void) imagePickerController:(UIImagePickerController *)picker


didFinishPickingImage:(UIImage *)image2 editingInfo:(NSDictionary
*)editingInfo;
- (void) imagePickerControllerDidCancel:(UIImagePickerController
*)picker;
@end

Bien que la classe GlassAppDelegate soit plus complexe, elle est comparable la classe
Exemple2_Chapitre1AppDelegate de la section prcdente. Elle joue le rle de dlgu
pour lapplication et dautres types dvnements, alors que limplmentation QuickConnectiPhone utilise la classe QuickConnectViewController comme dlgu pour tous
les vnements autres que ceux du dlgu de lapplication.
La mthode applicationDidFinishLaunching est comparable celle de la classe
Exemple2_Chapitre1AppDelegate. Pour que ce soit plus clair, seule une partie du code
source de la mthode applicationDidFinishLaunching de PhoneGap est donne ciaprs. Le code restant sera tudi en dtail la Section 8 et au Chapitre 7.
1
2

-(void)applicationDidFinishLaunching:
...
webView.delegate = self;

iPhone Livre Page 25 Vendredi, 30. octobre 2009 12:04 12

Chapitre 1

Dvelopper avec Dashcode et Xcode

25

...
3

[window addSubview:viewController.view];
...

La ligne 2 est intressante. linstar de la version de Exemple2_Chapitre1AppDelegate


tudie la Section 4, elle affecte un objet UIWebView comme vue secondaire de la fentre
principale. Autrement dit, lobjet UIWebView est utilis comme zone daffichage pour
lapplication.
Puisque vous connaissez prsent limplmentation de la principale mthode dlgue de
lapplication dans QuickConnectiPhone et PhoneGap, vous tes prt comprendre lutilisation de la classe UIWebView pour afficher et excuter une application JavaScript.

Section 6 : embarquer du contenu web


avec QuickConnectiPhone
Pour afficher du contenu web, par exemple des applications JavaScript ou de simples
pages web, dans votre application, vous devez utiliser la classe UIWebView. Toutes les
mises en uvre des applications hybrides, que ce soit avec QuickConnectiPhone ou
PhoneGap, emploient cette classe. Si vous souhaitez vous amuser avec les polices de
caractres dans une application, par exemple plusieurs polices, dans diffrentes tailles et
couleurs, vous devez utiliser UIWebView, moins que vous ne souhaitiez dessiner le texte
vous-mme. La classe UIWebView est simple dutilisation car elle sait comment interprter
le contenu HTML et CSS, ainsi que le code JavaScript. Cela permet de crer facilement
des prsentations textuelles, ou dautres types, complexes.
UIWebView est en ralit une enveloppe autour du moteur de rendu WebKit utilis dans le
navigateur Safari, dans Adobe Air, dans Android, dans les tlphones Nokia et dans
plusieurs autres applications, notamment celles livres avec Mac OS X, comme Mail.
Dashcode est galement un grand utilisateur du moteur WebKit.
Nous lavons mentionn dans les deux sections prcdentes, pour quune vue web soit
incluse dans une application lobjet UIWebView doit tre ajout comme vue secondaire
dune autre vue de lapplication. Pour cela, la mthode loadView de la classe QuickConnectViewController est invoque.
La mthode loadView contient diffrents lments qui permettent dexprimer des comportements dans une application JavaScript. Par exemple, elle fournit le code qui redimensionne linterface utilisateur de lapplication de manire ladapter la taille de lcran.

iPhone Livre Page 26 Vendredi, 30. octobre 2009 12:04 12

26

Dveloppez des applications pour liPhone

Cette possibilit est dsactive par dfaut, car linterface utilisateur doit tre initialement
conue la taille adquate.
La partie intressante de loadView permet laffichage de linterface conue dans Dashcode prcdemment dans ce chapitre. Lextrait de code suivant montre comment liPhone
insre ce contenu dans lapplication. Il commence par calculer la taille et le point dorigine
pour laffichage de lobjet UIWebView. Pour cela, il obtient la taille et lemplacement du
cadre daffichage de lapplication.
La variable webFrame, dont le type est une structure CGRect, contient ces informations
obtenues par lenvoi du message applicationFrame lcran principal de lapplication.
La structure CGRect est constitue de deux lments : un CGPoint, nomm origin, qui
reprsente les coordonnes X et Y du point suprieur gauche, et un CGSize, qui reprsente
la taille du rectangle exprimer sous forme dune hauteur et dune largeur :
CGRect webFrame = [[UIScreen mainScreen] applicationFrame];
webFrame.origin.y -= 20.0;

Les coordonnes X et Y, la largeur et la hauteur dun CGRect sont des nombres rels utiliss pour enregistrer un nombre de pixels. La seconde ligne du code prcdent montre
comment changer la position verticale courante enregistre dans la variable webFrame.
Elle dcale lorigine vers le haut de vingt pixels. Cette opration est ncessaire pour recouvrir un espace laiss vide dans la vue en raison de labsence dune barre doutils en haut de
la fentre daffichage.
Cette barre doutils est visible dans de nombreuses applications standard, comme lapplication Rglages utilise pour configurer liPhone. Elle a t retire des modles afin
daugmenter la place disponible sur lcran pour lapplication. Si vous souhaitez disposer
des boutons Suivant et Prcdent proposs par cette barre doutils, vous devez la crer
dans votre application laide de Dashcode.
Aprs avoir enregistr dans la variable webFrame lemplacement et la taille souhaits pour
laffichage du contenu web, elle est utilise pour initialiser un objet UIWebView nomm
aWebView. Les lignes 1 et 2 du code suivant montrent cette opration. Notez quelle
ressemble lallocation de QuickConnectViewController examine prcdemment dans
ce chapitre. Les principales diffrences sont lenvoi du message alloc la classe UIWebView et lenvoi du message initWithFrame lobjet UIWebView qui vient dtre allou,
avec le passage de la structure webFrame qui a t cre et modifie dans lextrait de code
prcdent. Lobjet aWebView est positionn et dimensionn conformment aux valeurs
contenues dans webFrame.
1 UIWebView *aWebView = [[UIWebView alloc]
2
initWithFrame:webFrame];

iPhone Livre Page 27 Vendredi, 30. octobre 2009 12:04 12

Chapitre 1

Dvelopper avec Dashcode et Xcode

27

3 self.webView = aWebView;
4 aWebView.autoresizesSubviews = YES;
5 aWebView.autoresizingMask=(UIViewAutoresizingFlexibleHeight
6

| UIViewAutoresizingFlexibleWidth);

7 // Fixer le dlgu du WebView lui-mme.


8 [aWebView setDelegate:self];

Le nouvel objet UIWebView est enregistr dans lattribut webView de QuickConnectViewController par le code de la ligne 3 afin quil soit possible dy accder ultrieurement
depuis dautres mthodes de QuickConnectViewController. Ce point est essentiel pour
lutilisation de lacclromtre, de la localisation GPS et des autres possibilits dcrites au
Chapitre 4.
Les lignes 5 6 illustrent la capacit de lobjet aWebView se redessiner lui-mme. Si
vous le pouvez, vitez lajout de vues secondaires. La ligne 4 stipule que, si aWebView
change de taille, les vues secondaires doivent galement tre redimensionnes. La syntaxe
employe prcise que, si la largeur de aWebView change en raison dune rotation, les vues
secondaires quil contient doivent galement changer de largeur dun facteur identique.
Les lignes 5 et 6 indiquent que la largeur et la hauteur de aWebView seront galement
modifies. Lorsque liPhone est bascul, il est frquent de passer la vue courante en mode
paysage, ou de len sortir, et de la redimensionner pour quelle corresponde aux nouvelles
largeur et hauteur de lappareil. Si les lignes 5 et 6 taient retires ou places en commentaires, lapplication basculerait toujours, mais la largeur et la hauteur de aWebView ne
seraient pas affectes. Une grande zone vide apparatrait alors droite de lapplication en
mode paysage. Il est rare de trouver des applications qui basculent sans se redimensionner.
La ligne 8 envoie aWebView un message pour lui indiquer que lobjet QuickConnectViewController courant, connu sous le nom self, joue le rle de dlgu de lobjet aWebView. Cela permet dimplmenter plusieurs mthodes facultatives de UIWebViewDelegate
dans la classe QuickConnectViewController. Le Tableau 1.1 recense ces mthodes.
Si vous en avez besoin, vous pouvez ajouter chacune de ces mthodes facultatives la
classe QuickConnectViewController. Le modle a dj ajout webView:shouldStartLoadWithRequest, webView:DidStartLoad, webView:DidFinishLoad et webView:didFailLoadWithError.
aWebView tant prt, il est temps prsent dindiquer le contenu qui doit tre charg et de
dclencher ce chargement. Pour cela, lemplacement du fichier index.html, qui fait partie
des ressources de lapplication, doit tre dtermin. Heureusement, comme le montrent les
lignes 3 et 4, la classe NSBundle qui reprsente lapplication sur le disque dispose dune
mthode nomme pathForResource:ofType.

iPhone Livre Page 28 Vendredi, 30. octobre 2009 12:04 12

28

Dveloppez des applications pour liPhone

Tableau 1.1 : LAPI de UIWebView

Signature de la mthode

Invocation

-(BOOL)webView:(UIWebView *) Juste avant que la


vue ne commence
webView shouldStartLoadWithRequest:(NSURLRequest *) charger le contenu.
request navigationType:
(UIWebViewNavigationType)
navigationType

Paramtres
webView la vue qui va charger le contenu.
request lemplacement du contenu
charger.

navigationType le type daction utilisateur qui dclenche le changement de la


page.
options de UIWebViewNavigationType
LinkClicked, FormSubmitted, BackForward, Reload, FormResubmitted et
Other.

- (void)webViewDidStartLoad:(UIWebView *) webView

Aprs que la vue a


commenc le chargement du contenu.

webView la vue qui charge le contenu.

- (void)webViewDidFinishLoad:(UIWebView *) webView

Aprs que la vue a


termin avec succs
le chargement du
contenu.

webView la vue qui charge le contenu.

- (void)webView:(UIWebView *)
webView didFailLoadWithError:(NSError *) error

Si la vue na pas
russi charger le
contenu.

webView la vue qui tente de charger le


contenu.

error un objet qui reprsente lerreur


gnre.

La mthode pathForResource:ofType prend deux chanes de caractres en argument. La


premire correspond au nom du fichier (la chane "index") et la seconde correspond
lextension du fichier (la chane "html"). Cet appel gnre le chemin complet du fichier
sur votre machine et lenregistre dans la variable locale filePathString. Ce chemin est
ensuite utilis pour crer un objet qui reprsente une URL vers le fichier, puis un objet
aRequest de type NSURLRequest qui reprsente llment charger (voir les lignes 7 et 8).
1
2
3
4
5
6

// Dterminer le chemin du fichier index.html dans le


// rpertoire Resources.
NSString *filePathString = [[NSBundle mainBundle]
pathForResource:@"index" ofType:@"html"];
// Construire lURL et la requte pour le fichier index.html.
NSURL *aURL = [NSURL fileURLWithPath:filePathString];

iPhone Livre Page 29 Vendredi, 30. octobre 2009 12:04 12

Chapitre 1

7
8
9
10
11
12

Dvelopper avec Dashcode et Xcode

29

NSURLRequest *aRequest = [NSURLRequest


requestWithURL:aURL];
// Charger le fichier index.html dans la vue web.
[aWebView loadRequest:aRequest];
// Ajouter la vue web la vue de contenu.
[contentView addSubview:aWebView];

la ligne 6, lobjet NSURL reoit le message fileURLWithPath. Puisquun fichier est


charg directement depuis le disque, ce message est bien adapt. Cela suffit pour les applications hybrides QuickConnectiPhone, mais, si vous utilisez une autre implmentation et
chargez une page directement depuis le Web, le message doit tre URLWithString, avec
en paramtre une URL complte du type http://www.byui.edu.
Aprs avoir cr lobjet NSURLRequest, le chargement rel de lURL est dclench par
lenvoi du message loadRequest lobjet aWebView de type UIWebView. Lobjet NSURLRequest, reprsent par la variable aRequest, est pass comme seul paramtre de ce
message.
Aprs le chargement de la requte, aWebView est ajout la vue principale de contenu en
lui envoyant le message addSubview avec lobjet UIWebView en paramtre. Si cet appel
nest pas effectu, la page est charge et pleinement active, mais elle nest pas affiche.

Section 7 : embarquer du contenu web avec PhoneGap


Contrairement QuickConnectiPhone, PhoneGap dfinit lemplacement dun fichier
HTML dans la mthode dlgue applicationDidFinishLaunching prsente la
Section 5. Nanmoins, une grande partie de la procdure daffichage du contenu web dans
lapplication reste identique.
Tout comme dans le cas de QuickConnectiPhone dcrit la section prcdente, PhoneGap
doit obtenir un chemin vers un fichier dans le paquetage de distribution de lapplication.
Cette fois-ci, le fichier se nomme url.txt la place du fichier index.html de QuickConnect.
Cette opration est ralise aux lignes 8 12 du code ci-aprs.
Tout dabord, et comme la section prcdente, lobjet NSBundle qui reprsente lapplication sur le disque est cr. Le message pathForResource lui est ensuite envoy avec les
valeurs url et txt en paramtres. Si le chargement de ce fichier russit, la chane de caractres contenue dans le fichier url.txt est affecte la variable locale theURLString
(lignes 10 12).
1
2
3

NSString * htmlFileName;
NSString * urlFileName;
htmlFileName = @"index";

iPhone Livre Page 30 Vendredi, 30. octobre 2009 12:04 12

30

Dveloppez des applications pour liPhone

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

urlFileName = @"url";
NSString * urlPathString;
NSBundle * thisBundle = [NSBundle bundleForClass:
[self class]];
if (urlPathString = [thisBundle
pathForResource:urlFileName ofType:@"txt"]) {
NSString * theURLString =
[NSString stringWithContentsOfFile:
urlPathString];
appURL = [NSURL URLWithString:theURLString];
[appURL retain];
NSURLRequest * aRequest =
[NSURLRequest requestWithURL:appURL];
[webView loadRequest:aRequest];
}

La ligne 13 convertit la chane lue depuis le fichier url.txt en un objet NSURL qui sert
crer une requte. Nous lavons vu la section prcdente, cette requte est passe en
paramtre webView en utilisant le message loadRequest.
Par ces deux implmentations du mme comportement, vous pouvez constater que, malgr
leurs lgres diffrences, elles sont quasiment identiques. Toutes les mises en uvre
dapplications hybrides utilisent lapproche suivante :

obtenir une chane dURL ;

crer un NSURL partir de la chane ;

crer un NSURLRequest partir du NSURL ;

utiliser le message loadRequest de UIWebView avec le NSURLRequest en paramtre.

Si vous dcidez dcrire votre propre implmentation, vous devez respecter cette procdure.

En rsum
Pour crer des applications hybrides pour liPhone, vous avez besoin dune petite enveloppe Objective-C pour lapplication HTML, CSS et JavaScript. Dashcode est un outil
puissant qui permet de crer rapidement et facilement une application JavaScript dynamique, que vous pouvez embarquer en utilisant cette enveloppe. Les modles dapplication
QuickConnectiPhone pour Dashcode et Xcode, ainsi que le modle PhoneGap pour
Xcode, acclrent la cration dune application en incluant dans votre projet le code rptitif employ dans toutes les applications hybrides. Comme le montrent les Chapitres 3, 4
et 6 8, les modles Xcode apportent le code Objective-C et JavaScript dont vous avez

iPhone Livre Page 31 Vendredi, 30. octobre 2009 12:04 12

Chapitre 1

Dvelopper avec Dashcode et Xcode

31

besoin pour crire des applications hybrides qui exploitent les possibilits suivantes en
JavaScript :

PhoneGap
donnes de lacclromtre ;
donnes de localisation GPS ;
vibreur de lappareil.

QuickConnectiPhone
donnes de lacclromtre ;
donnes de localisation GPS ;
vibreur de lappareil ;
sons systme personnaliss ;
enregistrement et lecture audio ;
affichage des dates standard et slecteurs de date et dheure ;
accs aux bases de donnes SQLite livres avec lapplication et celles de UIWebView lors de lexcution de lapplication.

Grce aux modles Dashcode et Xcode, vous pouvez crer des applications pour liPhone
plus rapidement que jamais.

iPhone Livre Page 32 Vendredi, 30. octobre 2009 12:04 12

iPhone Livre Page 33 Vendredi, 30. octobre 2009 12:04 12

2
Modularit JavaScript
Lorsque lon mentionne JavaScript, deux caractristiques viennent habituellement lesprit :
compatibilit internavigateurs et complexit. Ce chapitre explique comment viter la
complexit dans les applications hybrides pour liPhone et apporte le code source qui permet
de mettre en uvre facilement et rapidement un comportement complexe, sans remettre en
cause la flexibilit. Avec les applications hybrides pour liPhone, la compatibilit internavigateurs nest pas un problme car seul le moteur WebKit de Safari est utilis. Il est ainsi
beaucoup plus facile dcrire des applications JavaScript intressantes et amusantes.

Section 1 : modularit
Le concept de modularit existe depuis longtemps, que ce soit dans linformatique ou
dans dautres secteurs industriels. Lessence de la modularit se trouve dans la phrase
"construire partir de pices interchangeables". Si les pices sont des modules rellement
interchangeables, elles doivent tre capables de prendre la place dune autre sans que cela
ncessite, ou presque, une modification des lments qui interagissent avec elles. Dans le
domaine du logiciel, il sagit gnralement dune API commune qui ne change pas.

iPhone Livre Page 34 Vendredi, 30. octobre 2009 12:04 12

34

Dveloppez des applications pour liPhone

Lindustrie du divertissement aurait quelques soucis si chaque film tait produit sur un
support diffrent, car un systme de lecture diffrent serait alors ncessaire pour chaque
film. Si un fabricant dautomobiles ne standardisait pas la liaison entre le moteur et la
bote de vitesses, chaque combinaison moteur-bote devrait tre ralise la main. Les
cots monteraient en flche et la qualit en ptirait. Dans lindustrie du logiciel, les tentatives
pour crer du code modulaire rutilisable ont t nombreuses. Aujourdhui, elles prennent
la forme de frameworks.

Dfinition dun module


Pour quun module existe, il doit prsenter deux caractristiques : cohsion forte et
couplage faible.
Une cohsion forte signifie que le module a un rle clairement dfini et quil fait le ncessaire pour le jouer. Il existe pour remplir un objectif, comme grer une activit, et il agit
en ce sens.
Un couplage faible signifie que le module ne dpend pas dune connaissance du fonctionnement interne dautres modules et quaucun autre module ne connat le sien. Pour y
parvenir, il faut crer et utiliser une interface solide.
Lorsque ces deux caractristiques sont l, un module est n.

Ltude des frameworks est intressante. En gnral, un compromis a t fait entre la facilit dutilisation du framework et sa flexibilit. Si le dveloppeur du framework nest pas
attentif, il peut obtenir un framework avec lequel la mise en uvre des choses non importantes est facile, tandis que celle des besoins de lingnieur ou du programmeur est difficile.
Souvent, pour que le framework soit simple demploi et flexible, son extensibilit est
sacrifie, ce qui est le cas de Ruby on Rails. Ce framework est vraiment gnial, mais il
sadapte mal un environnement dentreprise sans passer par la mise en place dun matriel en cluster. Sa facilit dutilisation est donc rduite et les cots augmentent. Alors,
comment un framework peut-il tre extensible, facile utiliser et flexible ? La rponse se
trouve dans une modularit parfaitement applique et tudie.
Bien quils ne soient pas toujours enseigns ou rvls, certains types de modules permettent de faciliter le dveloppement de logiciels. Ces modules, quelque peu secrets, sont
connus sous les termes contrleurs frontaux et contrleurs dapplication.
Les exemples de ce chapitre montrent comment crer et utiliser ces modules et comment
ils permettent de faciliter et dacclrer le dveloppement dune application.

iPhone Livre Page 35 Vendredi, 30. octobre 2009 12:04 12

Chapitre 2

Modularit JavaScript

35

Section 2 : modularit avec le framework JavaScript


QuickConnect
Dans les modles Dashcode et Xcode, le framework JavaScript est conu pour minimiser
lutilisation du processeur et de la mmoire, tout en restant facile employer. Puisquil est
conu de manire hautement modulaire, chaque composant ralise une chose, la fait bien
et la fait rapidement.
La conception se fonde sur un paradigme de commande-rponse. Lorsque vous envoyez
une commande, les modules excutent les fonctions ncessaires qui lui sont associes. La
Figure 2.1 illustre ce flux de traitement dans une application dont la conception se fonde
sur cette approche. Le traitement commence ltape 1 et se poursuit tout au long du
framework en respectant la numrotation des flches.
Figure 2.1
Le flux de traitement
associ une seule
commande.

Requte

Contrleur
frontal
1

12
Contrleur
dapplication

Fonctions
de contrle
de la validation

10

Fonctions
de contrle
mtier
5

Fonctions
de contrle
de l'affichage
8

Objet d'accs la base de donnes

Base de
donnes
SQLite

11

iPhone Livre Page 36 Vendredi, 30. octobre 2009 12:04 12

36

Dveloppez des applications pour liPhone

Les seuls lments du flux qui ne sont pas dj crs sont les diffrentes fonctions de
contrle propres au fonctionnement de lapplication. Des exemples de ces modules applicatifs spcifiques seront donns tout au long de cet ouvrage.
Lexamen des donnes saisies par lutilisateur se fait par lintermdiaire des fonctions de
contrle de la validation (ValCF, Validation Control Function). Les fonctions de contrle
mtier (BCF, Business Control Function) servent obtenir des donnes partir dune base
de donnes, dun serveur web ou dune autre source, ou enregistrer des donnes. Les
fonctions de contrle de laffichage (VCF, View Control Function) sont employes pour
mettre jour la vue prsente lutilisateur.
Prenons un exemple. Supposons que vous souhaitiez collecter des informations sur lutilisateur actuel partir dun formulaire qui comprend un bouton Envoyer. Ces informations
sont ensuite places dans une base de donnes SQLite et lutilisateur est inform du succs
de cet enregistrement. Pour cela, vous devez crer trois fonctions de contrle : une ValCF
pour garantir que les donnes saisies rpondent aux standards dfinis par lapplication, une
BCF pour enregistrer les informations dans la base de donnes et une VCF pour dclencher
laffichage des messages de succs.
Toutes les fonctionnalits ne sont pas ncessairement associes aux trois types de fonctions de contrle. Par exemple, une application de jeu na pas forcment besoin dune
ValCF chaque fois que lutilisateur dclenche un comportement.
La Figure 2.1 montre que ces diffrentes fonctions de contrle nont pas besoin de
communiquer lune avec lautre. Les modules du framework sont conus pour un tel fonctionnement. Vous devez simplement crire les fonctions de contrle et les associer des
commandes. Grce cette conception, chaque fonction de contrle comprend seulement
quelques lignes de code et est immdiatement oprationnelle.
Puisque la conception est modulaire, vous pouvez facilement appliquer le concept de division du travail. Si vous rpartissez la cration de ces fonctions de contrle au sein dune
quipe, que ce soit en fonction de la commande ou de leur type, les dveloppements
peuvent se faire rapidement en parallle. Pour de plus amples informations concernant ces
fonctions de contrle et leur cration, consultez les Sections 4 et 5.
Lorsquelles sont bien crites, les fonctions de contrle peuvent tre utilises pour
plusieurs commandes. Par exemple, vous pourriez dfinir plusieurs commandes pour
actualiser la mme partie de lcran. Avec une telle conception, il est possible dassocier
une VCF qui actualise cette partie de la vue pour toutes les commandes.
Le Tableau 2.1 montre que le contrleur frontal de lapplication reprsente la passerelle au
travers de laquelle toutes les requtes dexcution doivent transiter. En obligeant toutes les

iPhone Livre Page 37 Vendredi, 30. octobre 2009 12:04 12

Chapitre 2

Modularit JavaScript

37

requtes passer par ce contrleur, il devient beaucoup plus facile de prdfinir lordre des
excutions dans lapplication.
Tableau 2.1 : LAPI du contrleur frontal

Mthode

Valeur de retour

Paramtres

handleRequest(aCmd, paramArray)

void

aCmd une chane unique qui reprsente le comportement traiter, par


exemple "displayBlogEntries".
paramArray un paramtre facultatif
constitu dun tableau de variables qui
peuvent tre requises pour le traitement.

Le contrleur frontal est comparable lenceinte qui entoure une ville fortifie : il
nexiste quune porte dentre et quune porte de sortie. En limitant les points daccs
possibles la ville, la dfense est plus facile et les citoyens peuvent vivre en meilleure
scurit. Lajout dun contrleur frontal votre application permet de la scuriser plus
facilement.
Dans le framework QuickConnectiPhone, le contrleur frontal est mis en uvre par la
fonction handleRequest. Elle est dfinie dans le fichier QuickConnect.js, qui, dans
Xcode, fait partie du groupe QCiPhone des ressources dapplication et, dans Dashcode, se
trouve dans le dossier QCiPhone. Si vous examinez le code, vous verrez comment les
fonctions de scurit et dordre dexcution sont mises en uvre.
Lors de son invocation, la fonction handleRequest reoit une commande et un tableau de
paramtres. La commande est obligatoire, contrairement au tableau de paramtres.
Le code suivant, qui correspond aux lignes 17 20 du fichier functions.js de lapplication
simpleCalc, illustre linvocation de la fonction handleRequest en rponse une action de
lutilisateur. Dans ce cas, lutilisateur a cliqu sur le bouton qui reprsente laddition (voir
Figure 2.2).
function add(event) {
handleRequest(math,new Array(+));
}

La commande math est passe en premier paramtre et un tableau contenant uniquement


le caractre + est pass en second paramtre. Dans ce cas, lutilisation dun tableau en
second paramtre peut sembler inutile, mais la conception impose ce paramtre et cette
solution est beaucoup plus flexible, comme vous le verrez plus loin.

iPhone Livre Page 38 Vendredi, 30. octobre 2009 12:04 12

38

Dveloppez des applications pour liPhone

Figure 2.2
Lapplication simpleCalc
aprs un appui sur le
bouton daddition.

La fonction add correspond au gestionnaire onclick dun bouton. Lors dun clic sur le
bouton correspondant, toutes les ValCF, BCF et VCF associes la commande math sont
excutes, avec le tableau de paramtres en argument. Vous remarquerez que les gestionnaires subtract, multiply et divide emploient la mme commande que la fonction add,
mais passent un caractre diffrent dans le tableau.
Dans notre exemple, lapplication rutilise le mme code de ValCF, BCF et VCF pour
chaque fonctionnalit. Il serait possible dutiliser une commande diffrente dans chaque
gestionnaire avec diffrentes BCF et de rutiliser ensuite les mmes ValCF et VCF, mais
les diffrentes BCF requises pour chaque type doprations arithmtiques seraient trs
semblables. Nous avons donc choisi de crer une seule BCF.
La Figure 2.3 illustre le flux de commande dans lapplication simpleCalc, aprs que
lutilisateur a cliqu sur lun des boutons dopration arithmtique. Dans cet exemple,
deux ValCF sont excutes pour dterminer si le traitement peut se poursuivre.
Noubliez pas que la conception modulaire montre ici fait respecter lordre des appels
de fonctions.

iPhone Livre Page 39 Vendredi, 30. octobre 2009 12:04 12

Chapitre 2

Figure 2.3
Ordre dexcution des
fonctions de contrle
associes la commande
math.

Modularit JavaScript

39

Flux dune commande

checkNumbersValCF
divisionByZeroValCF
calculateSolutionBCF
displaySolutionVCF

La premire ValCF vrifie que les deux valeurs saisies par lutilisateur sont des nombres. La
seconde, divisionByZeroValCF, vrifie quune division par zro ne peut pas se produire.
Aprs la validation, la fonction calculateSolutionsBCF est invoque. Cette BCF effectue lopration arithmtique demande par lutilisateur. La fonction displaySolutionVCF
affiche ensuite le rsultat (voir Figure 2.2).
En revanche, si la requte ne franchit pas lune des ValCF, la conception modulaire prsente
dispose de fonctions de contrle pour grer cette situation.
Les fonctions de contrle des erreurs (ECF, Error Control Function) sont des fonctions de
contrle utilises pour traiter les cas derreur. Si lune des ValCF choue, la fonction
entryECF est appele (voir Figure 2.4). Elle signale lutilisateur une erreur dans les
valeurs quil a saisies.
Figure 2.4
La conception du flux
de la commande math.

math
checkNumbersValCF

badNum

divisionByZeroValCF

divZero

entryECF

calculateSolutionBCF
displaySolutionVCF

Comment la commande math est-elle associe aux quatre fonctions de contrle qui
doivent tre excutes ? QuickConnectiPhone fournit pour cela quatre fonctions utilitaires
(voir Tableau 2.2). Chacune delles associe une commande une fonction de contrle.

iPhone Livre Page 40 Vendredi, 30. octobre 2009 12:04 12

40

Dveloppez des applications pour liPhone

Tableau 2.2 : LAPI des fonctions dassociation

Mthode

Valeur de retour

Paramtres

MapCommandToValCF(command,
validationControlFunction)

void

command une chane unique qui reprsente le


comportement traiter, par exemple math.
validationControlFunction une fonction de
validation excuter lorsque la commande est
reue par handleRequest.

MapCommandToBCF(command,
businessControlFunction)

void

command une chane unique qui reprsente le


comportement traiter, par exemple math.
businessControlFunction une fonction
mtier excuter lorsque la commande est reue
par handleRequest.

MapCommandToVCF(command,
viewControlFunction)

void

command une chane unique qui reprsente le


comportement traiter, par exemple math.
viewControlFunction une fonction daffichage excuter lorsque la commande est reue
par handleRequest.

MapCommandToECF(command,
errorControlFunction)

void

command une chane unique qui reprsente le


comportement traiter, par exemple divZero.
errorControlFunction une fonction
derreur excuter lorsque la commande est reue
par handleRequest.

Le code suivant, qui correspond aux lignes 24 27 du fichier mappings.js, montre lassociation de la commande math aux fonctions de contrle, ainsi que celle des erreurs badNum
et divZero.
// Associer une commande plusieurs fonctions.
mapCommandToValCF(math,checkNumbersValCF);
mapCommandToValCF(math,divisionByZeroValCF);
mapCommandToBCF(math, calculateSolutionBCF);
mapCommandToVCF(math, displaySolutionVCF);
// Associer plusieurs commandes une fonction.
mapCommandToECF(badNum, entryECF);
mapCommandToECF(divZero, entryECF);

iPhone Livre Page 41 Vendredi, 30. octobre 2009 12:04 12

Chapitre 2

Modularit JavaScript

41

Un contrleur frontal bien conu ne doit tre crit quune seule fois et doit pouvoir tre
rutilis dans plusieurs applications. La conception particulire du contrleur frontal et du
contrleur dapplication prsente dans ce chapitre offre galement une solution simple
pour concevoir les comportements spcifiques de vos applications.
Puisque cette conception garantit que les fonctions de contrle de la validation sont excutes
en premier et sont suivies de toutes les BCF et VCF, lorganisation de la conception au
niveau des fonctions de lapplication devient plus facile (voir Figure 2.4).
Cette conception gnrale du framework garantit galement que les fonctions de contrle
sont excutes dans lordre dans lequel elles sont associes aux commandes. Dans le code
prcdent, la fonction checkNumbersValCF est toujours invoque avant divisionByZeroValCF.

Contrleurs dapplication
Un contrleur dapplication, fond sur le pattern de contrleur dapplication standard,
est utilis pour associer des commandes des fonctionnalits prcises. Ainsi, les implmentations du pattern impliquent gnralement une mappe dont les cls correspondent
aux commandes et les valeurs, aux fonctionnalits cibles.
Avec la conception dcrite dans ce chapitre, les valeurs associes aux cls de la mappe sont
des listes de fonctions. Cela permet au contrleur dexcuter plusieurs fonctions dans
lordre indiqu et daugmenter la modularit et la rutilisabilit des cibles de la fonction
de contrle.
Un contrleur dapplication bien conu permet dobtenir une application volutive, car
une fonctionnalit peut tre ajoute sans rcrire le fonctionnement interne de lapplication.
La mise en uvre du contrleur dapplication de QuickConnectiPhone en est un exemple.

Puisque vous savez prsent comment les commandes sont associes aux fonctions de
contrle, il est temps dexaminer la cration de ces dernires. La fonction checkNumbersValCF est un exemple relativement classique de ValCF. Elle se focalise sur une tche,
cest--dire vrifier uniquement que les valeurs saisies par lutilisateur sont des nombres.
Si la validation choue, elle invoque un contrleur dapplication, dispatchToECF, pour
traiter lerreur :
function checkNumbersValCF(parameters) {
// Vrifier que a et b sont des nombres.
var a = document.getElementById(a).value;

iPhone Livre Page 42 Vendredi, 30. octobre 2009 12:04 12

42

Dveloppez des applications pour liPhone

var b = document.getElementById(b).value;
if(isNaN(a) || isNaN(b)) {
dispatchToECF(badNum,Saisissez uniquement des nombres.);
return false;
}
return true;
}

Les ValCF retournent true si la validation est positive, sinon false. Cela permet darrter
immdiatement le traitement en cas dchec et, par voie de consquence, daugmenter la
scurit de lapplication.
Prcdemment, la fonction calculateSolutionBCF a t associe en tant que BCF la
commande math. Comme la plupart des BCF, elle obtient des donnes sur lesquelles
elle opre. Dans ce cas, elle prend ses donnes dans linterface utilisateur. Dans
dautres cas, une BCF peut prendre des valeurs dans une base de donnes ou, en utilisant AJAX, partir dun serveur sur Internet. Le code suivant montre limplmentation
de cette BCF :
function calculateSolutionBCF(parameters){
var a = document.getElementById(a).value;
var b = document.getElementById(b).value;
if(a ==
a =
}
if(b ==
b =
}

){
0;
){
0;

// valuer le rsultat de lopration.


var expression = a+parameters[0]+b;
var result = eval(expression);
return new Array(a, b, result);
}

la place de la valeur boolenne des ValCF, les BCF retournent un tableau dinformations. Il contient toute information que vous choisissez dinclure. Dans notre cas, les
deux valeurs saisies par lutilisateur et le rsultat calcul sont retournes, car ces
donnes seront ncessaires pour gnrer les informations affiches lutilisateur (voir
Figure 2.2).
Le calcul rel du rsultat se fait avec la fonction JavaScript eval. Cette fonction tente
dexcuter une chane qui contient un code JavaScript valide. Dans cet exemple, si

iPhone Livre Page 43 Vendredi, 30. octobre 2009 12:04 12

Chapitre 2

Modularit JavaScript

43

lutilisateur saisit les valeurs 3 et 5 et clique sur le bouton daddition, la variable expression contient la chane "3+5". Lorsque cette chane est passe eval, cette fonction
retourne 8.
Faites attention lorsque vous utilisez la fonction eval, car elle excute la chane, quelle
quelle soit. Dans lapplication simpleCalc, cela ne pose pas de problme, car la ValCF
vrifie que les valeurs a et b sont bien des nombres. Si les lments utiliss dans un appel
eval ntaient pas valids, des utilisateurs pourraient dcouvrir le fonctionnement
interne des applications et avoir des agissements nfastes, comme une attaque par insertion
SQL si la BCF accde une base de donnes.
displaySolutionVCF est un exemple simple de VCF. Comme les autres fonctions de
contrle, elle ralise une seule chose : actualiser le <div> qui contient la chane reprsentant
lopration arithmtique effectue et le rsultat calcul.
function displaySolutionVCF(data, parameters){
var result = data[0][0]+ +parameters[0] +
+data[0][1]+ = +data[0][2];
document.getElementById(display).innerHTML = result;
}

En gnral, les VCF actualisent le contenu HTML de la page principale. Par exemple, une
modification majeure de la vue consiste changer lintgralit de linterface graphique.
Notre exemple effectue une petite modification en affichant le calcul arithmtique effectu
et en ne touchant pas au reste de linterface graphique.
Les ECF peuvent tre simples ou complexes. Elles peuvent modifier des donnes enregistres ou tre aussi simples que la fonction entryECF suivante, qui reoit une chane de
caractres en paramtre et laffiche lutilisateur.
function entryECF(message){
document.getElementById(display).innerHTML = message;
}

En raison de sa simplicit, cette ECF peut tre utilise par les deux ValCF de notre application
en cas dchec de la validation.
Avec une bonne implmentation de la conception contrleur frontal-contrleur dapplication, vous pouvez focaliser la conception et limplmentation de lapplication sur le
comportement souhait, non sur les communications et les passages de donnes entre les
fonctions. La section suivante dcrit la mise en uvre dun contrleur frontal et de contrleurs
dapplication.

iPhone Livre Page 44 Vendredi, 30. octobre 2009 12:04 12

44

Dveloppez des applications pour liPhone

Section 3 : conception modulaire


dans QuickConnectiPhone
Comme la plupart des autres parties de limplmentation de la conception dcrite dans ce
chapitre, la fonction handleRequest est courte. Elle et la mthode pour laquelle elle sert
de faade occupent vingt-trois lignes. Les lignes qui nous intressent sont prsentes en
gras (7 21).
Puisque handleRequest implmente le contrleur frontal de la conception examine la
section prcdente, elle est responsable de lappel des quatre contrleurs dapplication.
Chaque contrleur dapplication prend en charge un type de fonction de contrle. Comme le
montre la ligne 7, dispatchToValCF est le premier contrleur dapplication invoqu.
Le Tableau 2.3 dcrit chaque fonction contrleur dapplication.
Tableau 2.3 : LAPI du contrleur dapplication

Mthode

Valeur de retour

Paramtres

dispatchToValCF
(aCmd, paramArray)

Boolen (true en cas de succs, false en cas dchec).

aCmd une chane unique qui


reprsente le comportement traiter, par exemple displayBlogEntries.

paramArray un paramtre facultatif constitu dun tableau de variables


requises pour le traitement.

dispatchToBCF(aCmd,
paramArray, callBackData)

Les donnes prtes tre affiches ou stop. Si stop est


retourn, le traitement de la
commande indique sarrte.

aCmd une chane unique qui reprsente le comportement traiter, par


exemple displayBlogEntries.

paramArray un paramtre facultatif constitu dun tableau de variables


requises pour le traitement.

callBackData un paramtre
facultatif gnr par le framework si
des appels asynchrones sont effectus
depuis une BCF associe la commande.

iPhone Livre Page 45 Vendredi, 30. octobre 2009 12:04 12

Chapitre 2

Modularit JavaScript

45

Tableau 2.3 : LAPI du contrleur dapplication (suite)

Mthode

Valeur de retour

Paramtres

dispatchToVCF(aCmd, data,
paramArray)

void

aCmd une chane unique qui reprsente le comportement traiter, par


exemple displayBlogEntries.
data un tableau constitu de toutes
les donnes gnres par les appels
aux BCF.

paramArray un paramtre facultatif constitu dun tableau de variables


requises pour le traitement.

dispatchToECF(aCmd,
errorMessage)

void

aCmd une chane unique qui reprsente le comportement traiter, par


exemple databaseDown.
errorMessage un message davertissement, journalis pour le dveloppeur ou affich lutilisateur, qui
doit tre suffisamment descriptif et
utile pour le type dutilisateur auquel
il est destin.

dispatchToValCF appelle toutes les ValCF qui ont t associes la commande indique
par la variable aCmd. Si les fonctions de validation russissent, dispatchToValCF retourne
la valeur boolenne true ; dans le cas o lune des ValCF choue, elle retourne false.
Puisque lappel dispatchToValCF est plac dans une instruction if, la poursuite du traitement de la requte est conditionne par le retour de la valeur true. Si ce nest pas le cas,
la requte entre dans la routine de traitement des erreurs, mais seulement si des ECF ont
t associes la commande principale. Dans lapplication simpleCalc, une telle association nexiste pas.
1
2
3
4
5
6
7
8
9

function handleRequest(aCmd, paramArray){


requestHandler(aCmd, paramArray, null);
}
function requestHandler(aCmd, paramArray, callBackData){
if(aCmd!= null){
if(dispatchToValCF(aCmd, paramArray)){
try{
var data = dispatchToBCF(aCmd,

iPhone Livre Page 46 Vendredi, 30. octobre 2009 12:04 12

46

Dveloppez des applications pour liPhone

10
11
12
13
14
15
16
17
18
19
20
21
22
23 }

paramArray, callBackData);
if(data!= stop){
dispatchToVCF(aCmd, data, paramArray);
}
}
catch(err){
logError(err);
}
}
else{
dispatchToECF(aCmd, chec de la validation);
}
}

Aprs que la requte a pass la validation, le module du contrleur frontal appelle le


contrleur dapplication suivant, dispatchToBCF. Cette fonction contrleur invoque les
BCF associes la commande de manire obtenir ou enregistrer des donnes.
Si une BCF retourne des donnes autres que stop, le contrleur frontal appelle les VCF
associes la commande. Pour cela, il invoque le troisime contrleur dapplication,
dispatchToVCF. Pour de plus amples informations concernant les BCF et les VCF, consultez
la Section 4.
Lobjectif du module du contrleur frontal mentionn prcdemment est doffrir une solution rapide et simple pour garantir un flux de calcul stable et scuris dans lapplication.
Lorsquun flux est employ de manire cohrente, il est beaucoup plus facile de crer et de
dboguer les applications. Par consquent, lorsque vous utilisez la version QuickConnectiPhone de la conception, il est ncessaire dinvoquer la fonction handleRequest si vous
voulez que lapplication fasse quelque chose.
Chaque fonction de contrle de lapplication dcrite au Tableau 2.3 joue un rle distinct et
permet la poursuite ou larrt du traitement de la commande en fonction des dcisions que
vous prenez dans vos ValCF et vos BCF. Elles correspondent la notion de module car
elles sont rutilisables, faiblement couples et fortement cohsives.
La fonction dispatchToValCF est une faade. Du point de vue comportement, elle est
identique la fonction dispatchToSCF, mais elles manipulent toutes deux des jeux de
donnes diffrents. Les ValCF servent valider la saisie de lutilisateur. Les fonctions de
contrle de la scurit (SCF, Security Control Function) permettent de garantir que les
donnes obtenues partir de sources distantes, comme des sites web, ne contiennent pas
du code malveillant. En raison de leur objectif semblable, il est prfrable de centraliser le
code rel et dutiliser des fonctions de faade pour invoquer la fonction check sousjacente.

iPhone Livre Page 47 Vendredi, 30. octobre 2009 12:04 12

Chapitre 2

Modularit JavaScript

47

Le code suivant, tir du fichier QuickConnect.js, prsente la fonction de faade dispatchToValCF et la fonction check sous-jacente. Vous le constatez, la fonction dispatchToValCF invoque check en lui passant ses deux paramtres, plus un autre. Ce paramtre
supplmentaire est une chane qui dcrit le type de mappe que la fonction check va utiliser.
Cette mappe, ou tableau associatif, contient toutes les associations entre les commandes et
un tableau de ValCF. Pour crer et associer des commandes des ValCF, consultez la
Section 2 de ce chapitre.
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

function dispatchToValCF(validationCommand, paramArray){


return check(validationCommand, validation, paramArray);
}
/*
* Cette fonction ne doit pas tre appele directement par le programmeur.
*/
function check(command, type, data){
var retVal = true;
/*
* Excuter toutes les fonctions par dfaut dfinies qui sappliquent toutes
les commandes.
*/
var map = securityMap;
if(type == validation){
map = validationMap;
}
var defaultFuncs = map[default];
if(defaultFuncs){
var numFuncs = defaultFuncs.length;
for(var i = 0; i < numFuncs; i++){
retVal = defaultFuncs[i](command, data);
if(retVal == false){
break;
}
}
}
/*
* Si les fonctions par dfaut ont russi, excuter celles spcifiques la
commande.
*/
if(retVal == true){
commandFuncs = map[command];

iPhone Livre Page 48 Vendredi, 30. octobre 2009 12:04 12

48

Dveloppez des applications pour liPhone

33
34
35
36
37
38
39
40
41
42
43
44 }

if(commandFuncs){
var numFuncs = commandFuncs.length;
for(var i = 0; i < numFuncs; i++){
retVal = commandFuncs[i](data);
if(retVal == false){
break;
}
}
}
}
return retVal;

la ligne 17, le code tente dobtenir un tableau des fonctions de contrle associes la
commande default. Autrement dit, vous pouvez crer une VCF qui, en lassociant
default, sera appele pour chaque commande envoye handleRequest.
Une ValCF par dfaut classique sassure quune association pour la commande passe
existe, que ce soit dans la mappe des BCF, des VCF ou les deux. Si la commande
nexiste pas dans ces fonctions, il ny a aucune raison de poursuivre le traitement de la
commande. Par consquent, elle stoppe alors les contrles de validit suivants et
retourne false.
En retournant false, elle conduit galement la fonction dispatchToValCF retourner
false immdiatement, ce qui conduit le contrleur frontal arrter le traitement. Cette
ValCF dtecte les commandes errones sans association avant quelles ne soient sources
de problmes ultrieurs dans lapplication.
Sil nexiste aucune ValCF par dfaut ou si la commande a pass toutes celles associes
default, la fonction check se poursuit en obtenant la liste des ValCF associes la
commande spcifique fournie en argument et les excute dans lordre.
Comme expliqu la Section 2, ce contrle pralable des saisies de tout type fait partie
des objectifs de la fonction dispatchToValCF et des ValCF que vous crez. Il permet
galement de sparer le code de validation et le code dexcution. Grce cette sparation,
ces deux parties du code sont parfaitement identifies et la maintenance de lapplication
est simplifie. Il facilite galement la cration du logiciel en simplifiant le processus de
conception (voir Section 2).

iPhone Livre Page 49 Vendredi, 30. octobre 2009 12:04 12

Chapitre 2

Modularit JavaScript

49

Section 4 : implmentation des contrleurs mtier


et daffichage
De ces deux contrleurs dapplication, le plus complexe est le contrleur mtier, tandis
que le plus simple est le contrleur daffichage simple. La fonction dispatchToBCF
appelle toutes les BCF associes une commande, mme si une ou plusieurs des BCF
effectuent des appels asynchrones. La fonction dispatchToVCF est plus simple car elle
ressemble fortement la fonction dispatchToValCF et les VCF ne sont jamais asynchrones.
Bien que le comportement de ces fonctions soit comparable, leur implmentation est totalement diffrente.
Nous lavons expliqu la Section 2, la fonction de contrle mtier dispatchToBCF est
invoque uniquement si les ValCF que vous avez dfinies et associes indiquent que le
traitement peut se poursuivre. Bien que cette fonction se fonde sur des ides quivalentes,
elle est bien diffrente de la mthode checkValidation.
La fonction dispatchToBCF est constitue de deux parties principales. La premire
correspond aux lignes 18 40 et concerne le tableau callBackData. Ce tableau reprsente
les donnes accumules au cours dun appel asynchrone. Si la BCF neffectue aucun appel
asynchrone, ce tableau est vide. Dans le cas contraire, par exemple avec un appel AJAX ou
un appel pour consulter une base de donnes, ce tableau contient les donnes ncessaires
lappel des autres BCF associes la commande. Les lignes 25 et 31 montrent que ce
tableau callBackData contient les rsultats retourns par toutes les BCF invoques avant
lappel asynchrone et les donnes gnres par celui-ci.

Dfinition dasynchrone
En informatique, nous avons coutume de raisonner de manire synchrone. Autrement dit,
les choses se font une la fois, dans un ordre dfini. Lors de lappel une fonction, on
sattend ce que chaque tape de la fonction soit excute dans lordre. Lorsque toutes
les tapes sont termines, la fonction retourne ou non une valeur.
Un comportement asynchrone est bien diffrent. Il ressemble plus une partie de football. Dans ce jeu, chaque joueur soccupe de la fonction attribue son poste, quelle que
soit lactivit des autres joueurs. Tout autre comportement serait stupide. Imaginez un
match dans lequel tous les joueurs attendraient que les autres joueurs aient fini leur
action avant de commencer bouger...
En informatique, un comportement asynchrone signifie quune fonction peut jouer son
rle, mais que le traitement continue sans attendre le retour de la fonction.

iPhone Livre Page 50 Vendredi, 30. octobre 2009 12:04 12

50

Dveloppez des applications pour liPhone

La ligne 34 ajoute au tableau results les donnes gnres par lappel asynchrone, dans
le cas o aucun appel de BCF prcdent na t effectu. Ainsi, aprs lexcution de
cette ligne, le reste du code voit le tableau results comme si aucun appel asynchrone
navait eu lieu.
La ligne 37 obtient lindice de la BCF qui a effectu lappel asynchrone. Ainsi, le reste du
code de la fonction dispatchToBCF sait combien de BCF associes la commande ont
dj t excutes. Les appels asynchrones constituent une "rupture" dans lexcution des
BCF associes la commande. La fonction dispatchToBCF ne sait pas quelles BCF ont
dj t excutes, jusqu ce quun indicateur soit inclus dans les donnes gnres par
lappel asynchrone.
Au Chapitre 7, cela est mis en place par les mthodes getData, setData, getNativeData
et setNativeData de la classe DataAccessObject. Si vous crez votre propre framework
qui autorise les appels asynchrones, vous devez crer un code semblable au suivant :
1 function dispatchToBCF(aCmd, paramArray, callBackData){
2
3
if(event == null){
4
event = window.event;
5
}
6
if(event!= null){
7
stopDefault(event);
8
}
9
window.curCmd = aCmd;
10
if(paramArray){
11
window.globalParamArray = paramArray;
12
}
13
else{
14
window.globalParamArray = new Array();
15
}
16
var results = new Array();
17
window.numFuncsCalled = 0;
18
if(callBackData){
19
if(callBackData[0]){
20
if(callBackData[1]){
21
var accumulatedDataFromCallback =
22
callBackData[1][3];
23
if(accumulatedDataFromCallback &&
24
accumulatedDataFromCallback.length > 0){
25
results = accumulatedDataFromCallback;
26
}
27
}

iPhone Livre Page 51 Vendredi, 30. octobre 2009 12:04 12

Chapitre 2

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

Modularit JavaScript

if(results.length == 0){
// results doit toujours tre un tableau.
// Les crochets ([]) sen assurent.
results = [callBackData[0]];
}
else{
results.push(callBackData[0]);
}
}
if(callBackData[1]){
window.numFuncsCalled = callBackData[1][1];
}
}
var stop = false;
if(aCmd){
var commandList = businessMap[aCmd];
callFunc = function(data){
if(data){
results.append(data);
window.globalBCFResults = results;
}
if(window.numFuncsCalled < commandList.length){
var funcToCall =
commandList[window.numFuncsCalled];
window.numFuncsCalled++;
var result = null;
try{
result = funcToCall(paramArray,
results);
}
catch(err){
dispatchToECF(runFailure,
err.message);
}
if(result!= null){
results[results.length] = result;
callFunc();
}
else{
stop = true;
}
}
}

51

iPhone Livre Page 52 Vendredi, 30. octobre 2009 12:04 12

52

Dveloppez des applications pour liPhone

72
73
74
75
76
77
78
79
80 }

if(commandList && commandList.length > 0){


callFunc();
}
}
if(stop){
return stop;
}
return results;

Les lignes 41 80 de la fonction de contrle dispatchToBCF illustrent la manire de raliser trois choses :

crer et utiliser des fonctions JavaScript anonymes ;

employer la rcursivit en JavaScript ;

appeler les BCF associes une commande.

Une fonction anonyme est une fonction qui est cre " la vole" lintrieur dune autre
fonction. Dans le code prcdent, la fonction callFunc, aux lignes 44 71, en est un
exemple. Cette fonction nexiste pas en dehors de dispatchToBCF. Comme nimporte
quelle fonction anonyme, elle est strictement limite la porte de la fonction dans
laquelle elle est dclare. Par ailleurs, les variables dclares dans la fonction conteneur
avant la dclaration de la fonction anonyme sont dans la porte et peuvent tre utilises
dans la fonction anonyme, mme si elles ne sont pas passes en paramtres.
Les lignes 43 et 44 en sont un exemple. La variable commandList est dfinie en dehors de
la fonction callFunc, elle ne lui est pas passe en paramtre, mais elle est employe dans
cette fonction. Elle est utilise aux lignes 50 et 51 pour obtenir la prochaine BCF excuter.
Les lignes 55 et 56 excutent cette BCF et enregistrent les rsultats de linvocation.
Un exemple de rcursivit se trouve la ligne 65, o la fonction callFunc sappelle ellemme. Cela se produit la fin de la fonction, uniquement si le rsultat de lappel la BCF
nest pas null. Ce type de rcursivit est appel rcursivit finale car la vrification se
trouve la fin de la fonction. Si elle se trouvait au dbut de la fonction, il sagirait dune
rcursivit initiale. La cascade dappels rcursifs est dclenche par lappel callFunc
la ligne 73.

Rcursivit
La rcursivit correspond lappel dune fonction par elle-mme.

iPhone Livre Page 53 Vendredi, 30. octobre 2009 12:04 12

Chapitre 2

Modularit JavaScript

53

Lorsque la fonction dispatchToVCF est invoque, une liste des fonctions de contrle associes la commande est obtenue (voir le code ci-aprs). Contrairement la fonction de
contrle de la validation, dispatchToVCF reoit en argument un tableau contenant les
lments qui correspondent aux rsultats des appels chacune des BCF.
linstar de la fonction dispatchToBCF, si lune des VCF retourne stop, aucune autre
nest excute. Cela permet aux programmeurs de terminer lexcution en faisant un appel
dispatchToECF.
function dispatchToVCF(aCmd, data, paramArray){
if(aCmd){
var vcfFuncList = viewMap[aCmd];
if(vcfFuncList == null){
vcfFuncList = new Array();
}
var numFuncs = vcfFuncList.length;
for(var i = 0; i < numFuncs; i++){
try{
retVal = vcfFuncList[i](data, paramArray);
}
catch(err){
debug(errorMessage(err));
}
if(retVal && retVal == stop){
break;
}
}
}
}

Aprs quune VCF a t obtenue, elle est invoque avec les donnes rsultantes de la BCF
et les paramtres dorigine, paramArray, envoys par lapplication la fonction handleRequest. Cela permet de passer des informations aux BCF et aux VCF invoques par les
contrleurs dapplication mtier et daffichage.

Section 5 : implmentation dun contrleur derreur


Contrairement aux autres contrleurs dapplication examins aux Sections 3 et 4, la mise
en uvre du contrleur derreur dans le framework QuickConnectiPhone nautorise
lassociation que dune seule ECF une commande. Autrement dit, chaque ECF doit grer
intgralement lerreur, ce qui inclut modifier des donnes enregistres, actualiser la vue
pour avertir les utilisateurs, etc.

iPhone Livre Page 54 Vendredi, 30. octobre 2009 12:04 12

54

Dveloppez des applications pour liPhone

Voici un exemple dimplmentation simple dun contrleur derreur :


function dispatchToECF(errorCommand, errorMessage){
var errorFunc = errorMap[errorCommand];
if(errorFunc){
return errorFunc(errorMessage);
}
}

Cette version obtient simplement lECF excuter et lui passe le message derreur. Pour
activer une telle gestion des erreurs, il faut effectuer un appel direct dispatchToECF,
sans passer par un appel handleRequest. La ligne de code suivante est extraite de la
fonction checkNumbersValCF :
dispatchToECF(badNum, Saisissez uniquement des nombres.);

Cet appel dispatchToECF contient le message qui doit tre affich afin dinformer
lutilisateur que seuls les nombres sont accepts.

Section 6 : tapes de cration dune fonctionnalit


de lapplication
Les Sections 3 5 ont expliqu ce qui se passe en coulisse lorsque vous utilisez limplmentation des contrleurs frontaux et dapplication propose par le framework QuickConnectiPhone. Mais quelles sont les tapes suivre pour mettre en uvre une fonctionnalit
de lapplication ? Les voici, dans lordre :
1. Crer les BCF pour obtenir ou enregistrer les donnes (voir Section 4).
2. Crer les VCF pour modifier linterface utilisateur (voir Section 4).
3. Crer les ValCF ncessaires la validation de la saisie de lutilisateur (voir Section 3).
4. Crer les ECF ncessaires la gestion des conditions derreur possibles (voir Section 5).
5. Associer toutes les fonctions de contrle une commande en utilisant les fonctions
mapCommandTo* correspondantes.
Aprs avoir termin ces cinq tapes, la nouvelle fonctionnalit est intgre lapplication.

iPhone Livre Page 55 Vendredi, 30. octobre 2009 12:04 12

Chapitre 2

Modularit JavaScript

55

En rsum
Lorsquelle est applique correctement, la modularit facilite lcriture de code, simplifie
sa maintenance et rduit sa taille. En gardant cela lesprit, ainsi que la rapidit dexcution,
limplmentation apporte par le framework QuickConnectiPhone chaque application
cre laide de ses modles facilite normment votre travail. Vous pouvez vous concentrer sur votre objectif, cest--dire crer et fournir une fonctionnalit vos utilisateurs.
Le framework soccupe de toutes les communications et des contrles internes.
En crivant des ValCF, des BCF, des VCF et des ECF, vous pouvez aisment focaliser
votre travail de manire augmenter la productivit. Dans le mme temps, vous augmentez
galement la qualit et la scurit de votre code.

iPhone Livre Page 56 Vendredi, 30. octobre 2009 12:04 12

iPhone Livre Page 57 Vendredi, 30. octobre 2009 12:04 12

3
Interfaces utilisateur
LiPhone permet de proposer des mthodes dinteraction uniques avec lutilisateur. Sur ce
tlphone, les anciennes mthodes de conception des interfaces ne suffisent plus. Votre
application doit offrir les interactions et les lments dinterfaces que les utilisateurs de
liPhone rclament. Ce chapitre explique comment procder. Il sintresse galement au
guide dinterface utilisateur employ par Apple pour dcider de lajout des applications
dans lApp Store. Un module de redimensionnement, de rotation et de glisser-dposer
est galement dcrit afin que vous appreniez traiter les vnements lis au toucher et
aux gestes en JavaScript. Ces nouveaux types dvnements JavaScript sont essentiels
la conception des interfaces utilisateur pour liPhone.

Section 1 : guide de linterface utilisateur dApple


Pour que tous les utilisateurs de liPhone partagent la mme exprience, Apple a rdig un
guide qui stipule les rgles suivre lors de la conception des interfaces utilisateur des
applications pour liPhone. Cette section introduit le HIG (Human Interface Guide) pour
liPhone de manire concise et simple. Sa version intgrale peut tre consulte ladresse
http://developer.apple.com/iphone/library/documentation/UserExperience/Conceptual/
MobileHIG/Introduction/Introduction.html.

iPhone Livre Page 58 Vendredi, 30. octobre 2009 12:04 12

58

Dveloppez des applications pour liPhone

Le HIG pour liPhone trouve ses origines dans les guides crs prcdemment pour OS X
et le dveloppement web pour liPhone. Ce nouveau guide se fonde sur les points forts des
prcdents et ajoute de nouveaux aspects spcifiques aux applications pour liPhone.
La place disponible sur lcran de liPhone est tellement limite que laffichage dun texte
lutilisateur peut vite devenir pnible. Pour les applications dont la fonction principale
nest pas de prsenter des donnes textuelles, il est prfrable demployer des images et
des icnes pour communiquer des ides et offrir des fonctionnalits utilisateur.
Labandon des informations textuelles se trouve au cur de liPhone. Cet appareil ne
prsente pas de menus droulants ou de rubans, et vos applications ne doivent pas en utiliser.
Si lapplication est bien conue, son utilisation doit se rvler intuitive. Si elle nest pas
intuitive, lapplication nest pas conue pour liPhone. Si elle est bien conue, elle na
besoin daucun guide de lutilisateur.
Les menus droulants ont prolifr car les applications nont plus un seul usage mais
plusieurs. Si vous examinez les applications bureautiques existantes, il est facile de voir
comment elles sont parties dapplications initialement simples, lusage bien dfini, pour
devenir des monstres de fonctionnalits.
Les logiciels de traitement de textes ne sont plus vraiment des traitements de textes. Ils
permettent de crer des mises en page sophistiques, sont capables dinclure des donnes
provenant dapplications totalement diffrentes et offrent mme un environnement de
dveloppement. Si cette enchre de fonctionnalits a permis de conserver la viabilit des
applications, celles-ci sont devenues volumineuses et lourdes.
Chaque application pour liPhone doit avoir un et un seul objectif ou fonction. Il doit tre
facile identifier et facile matriser par lutilisateur. En respectant les standards dApple,
vos applications seront plus facilement comprhensibles et apporteront lutilisateur une
exprience plus plaisante.
Le contrle de lapplication est un lment vital dans toute conception. Lutilisateur doit
disposer du plus grand contrle possible. Autrement dit, lapplication ne doit pas le
contraindre des comportements prcis. La limitation des options est vue dun mauvais
il dans les applications pour liPhone. Pour arriver ce rsultat, les vues dune application doivent tre organises plat. Les profondes hirarchies de vues augmentent la charge
de travail de lappareil et sont dconseilles.
Puisque les interactions avec liPhone se font par des gestes, comme le toucher et le
toucher multiple, lapplication doit galement les prendre en charge. Chaque zone de
toucher doit tre dimensionne de manire approprie pour que lutilisateur puisse la
slectionner. Normalement, la largeur et la hauteur dune zone de toucher doivent tre
gales 34 pixels. Si elles sont plus petites, par exemple pour gagner de la place sur

iPhone Livre Page 59 Vendredi, 30. octobre 2009 12:04 12

Chapitre 3

Interfaces utilisateur

59

lcran, lutilisateur risque davoir des difficults slectionner les lments et nen sera
que plus mcontent.
Mme si le balayement (swipe) et le pincement (pinch) sont des comportements pris en
charge, les utilisateurs peuvent avoir du mal savoir quils existent. Si vous souhaitez les
inclure, ajoutez des indicateurs visuels qui informent de leur disponibilit. Par exemple,
dans une application de type livre lectronique, ces indicateurs peuvent prendre la forme
de coins de page plis.
Le glisser-dposer est gnralement dconseill par le HIG, car la mme interaction de
lutilisateur sert habituellement au dfilement ou au dplacement panoramique. Toutefois,
il est facile de trouver des applications russies qui utilisent cette fonctionnalit. Apple a
mme crit en JavaScript un exemple excessivement complexe de ce comportement.
La seconde partie de ce chapitre explique comment mettre en uvre le glisser-dposer, le
pincement pour le redimensionnement et la rotation des lments de linterface.
Le Tableau 3.1 rcapitule les diffrents types de gestes reconnus et les comportements standard
associs. En respectant ces fonctionnements, la phase dapprentissage de lapplication est
rduite. En revanche, si vous redfinissez les comportements associs, elle devient plus longue.
Tableau 3.1 : Gestes reconnus par liPhone et comportements standard associs

Geste

Comportement

Toucher (tap)

Slection dun lment de linterface utilisateur.

Glissement (drag)

Dfilement ou dplacement panoramique pour un autre affichage.

Dfilement (flick)

Dfilement ou dplacement panoramique rapide. Une fois le


geste termin, le comportement doit se poursuivre.

Balayement (swipe)

Rvlation des composants cachs, comme des boutons de suppression dune ligne dune table ou des vues supplmentaires.

Double-toucher (double tap)

Centrage, puis zoom avant ou arrire.

Pincement vers lextrieur (pinch open)

Zoom avant.

Pincement vers lintrieur (pinch close)

Zoom arrire.

Toucher et maintien

Affichage dune vue agrandie.

LiPhone est un appareil rellement extraordinaire, mais la saisie dun texte peut tre pnible et lente compare lutilisation dun clavier standard. Autant que possible, essayez
dutiliser des slecteurs de donnes la place dune saisie directe. Dans les applications

iPhone Livre Page 60 Vendredi, 30. octobre 2009 12:04 12

60

Dveloppez des applications pour liPhone

hybrides, les slecteurs apparaissent lorsque lutilisateur active une balise HTML
<option>. Grce aux slecteurs, les utilisateurs matrisent plus rapidement votre application et leur niveau de frustration diminue. Le Chapitre 4 explique comment inclure des
slecteurs de date et dheure dans les applications hybrides.
Le document de standardisation des applications pour liPhone stipule que les cases
cocher et les boutons radio doivent tre vits. la place, il est prfrable dutiliser des
interrupteurs. Lapplication Rglages fournie avec chaque iPhone et iPod Touch les utilise
normment. La Figure 3.1 illustre les options de Safari que vous pouvez modifier dans
lapplication Rglages. Les dveloppeurs dapplications hybrides ont quelques difficults
viter les boutons radio et les cases cocher.
Figure 3.1
Les interrupteurs
utiliss pour les rglages
de Safari.

Loutil Dashcode utilis pour dvelopper linterface graphique des applications hybrides ne
dispose pas dune widget de type interrupteur, mais il est facile de la crer. Elle est constitue
dune bote avec une bordure interne, deux lments de texte, 1 et 0, et un bouton.
En utilisant les vnements de geste sur le bouton, il est facile de le faire glisser droite ou
gauche de manire rvler ltat de linterrupteur. La fonction de rappel ongestureend
dfinie pour le bouton permet de dtecter et denregistrer son tat allum (1) ou teint (0).
Servez-vous des boutons de rglage de Safari illustrs la Figure 3.1 pour crer les vtres.
En respectant ces rgles de base pour la conception, votre application satisfait aux exigences dApple pour sa distribution sur lApp Store et son fonctionnement correspond aux

iPhone Livre Page 61 Vendredi, 30. octobre 2009 12:04 12

Chapitre 3

Interfaces utilisateur

61

attentes de lutilisateur. Le non-respect de ces concepts risque de conduire au rejet de votre


application par Apple et par ses utilisateurs potentiels.

Section 2 : interfaces fondes sur les listes


et sur Navigateur
Certaines interfaces utilisateur de base pour liPhone se fondent sur les listes pour organiser
laffichage. Lapplication HistoryExample en est un exemple. Dans Dashcode, cette interface est cre de deux manires. La plus rapide consiste utiliser la partie Navigateur.
La partie Navigateur, qui se trouve dans la bibliothque des parties, peut tre dpose
directement sur lapplication pour crer une pile de vues indpendantes. Les vues constituent lunit daffichage principal avec laquelle les utilisateurs interagissent ; elles sont
souvent appeles, de manire errone, cran. Lorsquune partie Navigateur est ajoute
une application, deux vues sont ajoutes par dfaut, mais pas le code de basculement
dune vue lautre. Une barre den-tte comprenant un bouton de navigation est galement insre automatiquement. La Figure 3.2 prsente loutil Dashcode aprs lajout de la
partie Navigateur.

Figure 3.2
Ajout dune partie Navigateur dans Dashcode.

iPhone Livre Page 62 Vendredi, 30. octobre 2009 12:04 12

62

Dveloppez des applications pour liPhone

Il est inutile de modifier le bouton ajout automatiquement dans len-tte, car la partie
Navigateur ajuste le texte affich pour quil corresponde lintitul de len-tte de la vue
prcdente (si elle existe). Lorsque vous crez une application, vous devez modifier le
texte de len-tte, non celui du bouton, pour reflter le nom de lapplication ou toute autre
information approprie.
Deux vues avec des noms par dfaut sont insres dans le projet lors de lajout dune
partie Navigateur. En slectionnant longlet Attributs dans linspecteur, vous pouvez
voir ces vues et les renommer. La Figure 3.3 prsente lapplication HistoryExample aprs
avoir nomm les vues mainView et presidentsView. Vous remarquerez les options + et
dans la liste sous-prsentations. Ces boutons vous permettent dajouter dautres vues
et de retirer celles dont vous navez pas besoin.

Figure 3.3
Lapplication HistoryExample avec des vues et deux listes rectangulaires arrondies ajoutes
la vue principale.

Toutes les vues de lapplication sont gres depuis la liste sous-prsentations. Vous
remarquerez que, mme si la navigation dans lapplication correspond mainView >
ContinentsView > SouthAmericanView, toutes les vues sont directement des enfants de
stackLayout. Cest ainsi que les applications de ce type doivent tre dveloppes.
Dans les listes rectangulaires arrondies et les listes bout--bout, seul le premier lment de
la liste peut tre slectionn dans lcran Dashcode de conception de linterface graphique.

iPhone Livre Page 63 Vendredi, 30. octobre 2009 12:04 12

Chapitre 3

Interfaces utilisateur

63

Ce premier lment sert de modle pour les autres lments de la liste. Toute modification
de la couleur, du contenu ou de la taille de cet lment est applique tous les autres
lments de la liste. Cela inclut galement les gestionnaires dvnements affects. Tous
les lments des listes prsentes dans lapplication HistoryExample partagent le mme
gestionnaire dvnements onclick, la fonction changeView.
Le code de la fonction changeView, qui se trouve dans le fichier main.js, est donn ciaprs. Elle utilise les tiquettes et les valeurs saisies dans lcran des attributs de la vue
pour dterminer la nouvelle vue afficher. Pour examiner cette fonction, slectionnez la
vue, non le premier lment dtiquette. Dans votre application, cest l o vous ajoutez
les lments statiques de la liste (voir Figure 3.4).
function changeView(event)
{
var subViewName = event.target.object.value;
var displayName = event.target.innerText;
var browser = document.getElementById(browser).object;
browser.goForward(subViewName+View, displayName);
}

Figure 3.4
Affichage des attributs de la liste people de la vue principale, avec deux lments statiques ajouts.

iPhone Livre Page 64 Vendredi, 30. octobre 2009 12:04 12

64

Dveloppez des applications pour liPhone

En utilisant ces valeurs et en donnant le nom appropri aux vues, la mthode goForward
de lobjet browser permet de passer la vue suivante. Cette mthode prend deux arguments. Le premier est le nom de la vue vers laquelle basculer, le second, le texte afficher
dans len-tte de la vue. Si vous essayez de basculer vers une vue et si len-tte est modifi
sans que la vue change, cela signifie que le nom de la vue que vous tentez dafficher ne
correspond pas celui dune vue de votre application.
Lorsque vous crez des applications fondes sur des listes et des vues, vous devez faire
attention lorganisation des donnes. Si les informations sont places dans un trop grand
nombre de vues, lutilisateur trouvera la navigation exagrment complique. En ralit, si
vous ny prenez pas garde, vous pourriez rinventer la navigation de type DOS des annes
1970 et 1980.
Les applications base de listes et de vues ont de nombreuses utilisations, mais elles ne
sont pas toujours les plus attrayantes visuellement. Parfois, le changement de vues doit se
faire partir dun lment autre quune liste.

Section 3 : applications non fondes sur des listes


Bien que les utilisations des applications fondes sur les listes et les vues soient nombreuses,
rien noblige toutes les applications fondes sur les vues utiliser des listes pour accder
aux informations. Dautres indices visuels peuvent indiquer que toucher un lment
permet dafficher des informations supplmentaires. Lapplication PictureExample fournie
avec le framework QuickConnectiPhone en est un exemple.
En indiquant sur lcran quun lment peut tre touch, lutilisateur a tendance toucher
tous les lments pour savoir sils sont actifs. Si vous retenez cette approche, faites attention ne pas perturber vos utilisateurs par ces indices ou par les lments quils doivent
toucher pour contrler votre application.
Le code suivant prsente deux diffrences par rapport au code prcdent. Tout dabord,
chacune des images a besoin dun gestionnaire onclick ou ontouchstart pour dclencher le passage une vue secondaire. Dans cet exemple, une seule fonction, goSub, est
utilise pour grer les images touchables.
function goSub(event)
{
var stackLayout = document.getElementById(stackLayout).object;
stackLayout.setCurrentView(event.target.id+View, false);
}

iPhone Livre Page 65 Vendredi, 30. octobre 2009 12:04 12

Chapitre 3

Interfaces utilisateur

65

En affectant chaque image un id semblable au nom de la vue quil reprsente, il est


facile demployer une mthode pour changer de vue. Lexemple prcdent le montre,
lobjet stackLayout offre une mthode setCurrentView qui prend deux arguments :
lidentifiant de la vue vers laquelle basculer et un indicateur. Si lindicateur vaut true,
cela signifie que le changement de vue correspond un retour en arrire. Lidentifiant et
lindicateur permettent au programmeur de contrler les transitions dune vue une
autre.
Contrairement lapplication HistoryExample constitue de listes, de vues et dun en-tte
de navigation prconstruits, lapplication PictureExample ne comprend aucune barre de
navigation automatique. Cest pourquoi le programmeur doit crire le code de retour dune
vue secondaire la vue principale.
Les images de retour (marques par Back) dans les vues secondaires sont faites pour revenir la vue principale. Puisquil ne serait pas appropri que leffet visuel associ une
transition en arrire soit identique celui dune transition en avant, la valeur du second
paramtre de la fonction setCurrentView est fixe true. Il indique une transition
visuelle en arrire.
Le code de goMain prsent ci-aprs est associ au bouton Retour en tant que gestionnaire
onclick. Puisque le second argument vaut true, la transition associe mainView se fait
dans un sens oppos au comportement standard. Nous pouvons ainsi faire en sorte que
lutilisateur pense quune action prcdente est annule.
function goMain(event)
{
// Fixez la vue courante dun StackLayout.
var stackLayout = document.getElementById(stackLayout).object;
stackLayout.setCurrentView(mainView, true);
}

Par rapport aux applications fondes sur une partie Navigateur, lanimation du changement de vues offre dautres possibilits. Elle constitue un autre lment dinformation
donn lutilisateur. Lorsque lanimation utilise pour passer une vue nest pas identique celle employe pour dautres vues, lutilisateur sait que cette vue a quelque chose de
diffrent. La Figure 3.5 prsente la liste des vues secondaires et la fonction goMain dans
Dashcode.

iPhone Livre Page 66 Vendredi, 30. octobre 2009 12:04 12

66

Dveloppez des applications pour liPhone

Figure 3.5
Longlet des attributs de stackLayout montre les options de la transition.

Comme le montre le Tableau 3.2, il est possible dutiliser plusieurs types de transitions
dans une application, mais ce nest pas judicieux.
Tableau 3.2 : Transitions par dfaut disponibles dans Dashcode

Type de transition

Comportement

Dfiler

Une transition bidimensionnelle dans laquelle la nouvelle vue afficher arrive dans
la zone visible pendant que lancienne vue la quitte.

Dissolution

Une transition bidimensionnelle dans laquelle la vue afficher devient plus opaque tandis que lancienne vue devient plus transparente. Puisquelles se superposent, lancienne vue semble se transformer progressivement en la nouvelle
vue.

iPhone Livre Page 67 Vendredi, 30. octobre 2009 12:04 12

Chapitre 3

Interfaces utilisateur

67

Tableau 3.2 : Transitions par dfaut disponibles dans Dashcode (suite)

Type de transition

Comportement

Diapositive

Une transition bidimensionnelle semblable Dfiler. Dans ce cas, lancienne vue


reste sa place pendant que la nouvelle apparat et la recouvre, pour donner lutilisateur limpression dune pile de vues. Dans ce cas, une transition "en arrire" correspond entrer dans les dtails des vues de lapplication, tandis quune transition
"en avant" correspond un retour vers le dbut de la pile.

Fondu

Une transition bidimensionnelle semblable Dissolution. Dans ce cas, lancienne


vue reste opaque afin que les deux vues soient visibles la fin de la transition.
Lorsque cette transition se fait "en arrire", la nouvelle vue devient opaque et la
vue dorigine est intgralement affiche. Cette transition sert ajouter une nouvelle information ou fonctionnalit une vue existante, car les deux vues peuvent
accepter les vnements de toucher.

Rotation

Une transition tridimensionnelle qui provoque une rotation le long de laxe Y de


lappareil par rapport au centre de lancienne et de la nouvelle vue. Lutilisateur a
limpression que lancienne vue se trouve au premier plan de lapplication et que la
nouvelle se trouve larrire-plan. Cette transition nest gnralement pas utilise
dans les applications qui comprennent uniquement deux vues.

Cube

Une transition tridimensionnelle dans laquelle lutilisateur voit toutes les vues sur
les cts dun cube, qui pivote vers lavant ou larrire.

changer

Une transition tridimensionnelle dans laquelle lancienne vue semble glisser


depuis un ct et passer sous la nouvelle vue. Au cours de la transition, larrireplan de la nouvelle vue est transparent. la fin de la transition, cet arrire-plan
devient opaque.

Faire pivoter

Une transition tridimensionnelle dans laquelle lancienne et la nouvelle vue pivotent


autour de laxe Y de lappareil sur un des bords. Leffet obtenu est comparable une
porte pivotante.

Si lon en croit linterface de Dashcode, il semble que les seules directions possibles pour
ces transitions soient de droite gauche et de gauche droite, mais ce nest pas le cas. Des
mouvements de haut en bas et de bas en haut sont galement possibles.
Le code suivant est extrait du fichier setup.js de lapplication HistoryExample ; il a t
gnr par Dashcode. Vous le constatez, les types de transitions et leur direction sont indiqus pour toutes les vues. Si vous souhaitez les modifier, vous devez tout dabord dsactiver la gnration de code en allant dans le menu Prsentation > Arrter le gnrateur de
code.
var dashcodePartSpecs = {
...

iPhone Livre Page 68 Vendredi, 30. octobre 2009 12:04 12

68

Dveloppez des applications pour liPhone

"stackLayout": { "creationFunction": "CreateStackLayout",


"subviewsTransitions": [{ "direction": "right-left", "duration": "", "timing":
"ease-in-out", "type": "push" }, { "direction": "right-left","duration": "",
"timing": "ease-in-out", "type": "push" }, { "direction": "right-left",
"duration": "", "timing": "ease-in-out", "type": "push" }, { "direction":
"right-left", "duration": "", "timing": "ease-in-out", "type": "push" }, {
"direction": "right-left", "duration": "", "timing": "ease-in-out", "type":
"push" }] }
...
};

Puisque Dashcode gnre une grande partie du code votre place et remplace rgulirement le contenu du fichier setup.js, vous ne devez pas modifier celui-ci tant que lapplication nest pas termine. Il est plus facile deffectuer ces modifications aprs que le fichier a
t plac dans le modle QuickConnectiPhone pour Xcode car Dashcode nentre plus en
jeu et ne peut donc pas craser les modifications que vous effectuez.
Le code prcdent contient la dclaration de quatre objets JavaScript. Chacun commence
par le caractre {, se termine par } et contient les attributs direction, duration, timing
et type. Lun de ces objets, le deuxime, est prsent en gras afin de le distinguer des
autres.
Chacun de ces objets anonymes dfinit le comportement du passage dune vue une autre.
Lobjet prsent en gras dclare une transition de type Dfiler (voir Tableau 3.2). Elle
pousse la nouvelle vue de la gauche vers la droite avec une acclration au dbut de la
transition et un ralentissement la fin (synchronisation ease-in-out).
Les autres options de synchronisation sont ease-in, ease-out et par dfaut. La synchronisation par dfaut, dans laquelle la vitesse est constante, est utilise lorsque lattribut
timing de lobjet de dfinition est absent.
Nous lavons mentionn prcdemment, il existe dautres options pour lorientation de la
transition : de haut en bas (top-bottom) et de bas en haut (bottom-top). Elles sont valides
uniquement pour les transitions de type Diapositive et Dfiler.
Si vous choisissez de modifier les dclarations de ces objets, sachez que cela peut
provoquer des problmes dans une application plus complexe. Il semble quApple ait
interdit certains choix dans les options de transition car ils provoquent des dysfonctionnements dans le moteur WebKit de Safari et dans lobjet UIWebView des applications
hybrides.

iPhone Livre Page 69 Vendredi, 30. octobre 2009 12:04 12

Chapitre 3

Interfaces utilisateur

69

Section 4 : applications dimmersion


Les applications dimmersion sont en rupture totale avec lutilisation des vues pour
regrouper des informations et des contrles. Les jeux en sont la concrtisation la plus
frquente, mais certaines applications mdicales pour liPhone suivent galement cette
voie. Lide est que les interactions de lutilisateur avec lapplication soient naturelles,
fluides et, si possible, dans une seule vue.
Si les jeux utilisent cette approche sous sa forme extrme, elle peut galement tre
employe dautres manires. Cest notamment le cas dans les applications dimagerie
mdicale, o les possibilits tactiles de liPhone changent normment la manire dont les
mdecins interagissent avec les images.
Il ny a aucune raison pour que des dveloppeurs novateurs nappliquent pas cette solution
des applications dentreprise ou scientifiques. Souvent, de mauvaises dcisions mtier
sont prises car laffichage des lments dinformation connexes et complexes avec les
graphiques actuels est difficile. Pour examiner les donnes de manire diffrente, il faut
utiliser une autre forme daffichage.
Si des donnes peuvent tre prsentes sous forme non linaire sur lintgrit de lcran,
des informations complmentaires peuvent leur tre superposes afin didentifier des relations. Une version simple de cette mthode est employe dans les applications cartographiques pour non seulement afficher une route menant dun lieu un autre, mais
galement indiquer la densit du trafic sur cette route et les routes voisines. Les deux
lments dinformation sont superposs afin que lutilisateur puisse en dduire un motif
utile.
Cet ouvrage ne prtend pas fournir une solution pour la manipulation des donnes en vue
de leur affichage. Il suggre simplement que cette possibilit existe et quelle est
employe. Dans cette section, nous prendrons lexemple dun jeu.
Le jeu DollarStash est une variante de lapplication web Leaves dApple. Dans cette application, des images de feuilles sont ajoutes sur la page et tombent progressivement vers le
bas de lcran en tourbillonnant. Pour en faire un jeu, nous remplaons les feuilles par des
images de billets.
Lorsque lutilisateur touche un billet, la quantit dargent sur son compte est incrmente.
Si un billet disparat totalement avant que lutilisateur ne le touche, le solde du compte est
dcrment. Des groupes de billets sont affichs par vagues en haut de lcran. Chaque
vague contient un billet de plus que la prcdente. Lorsque le solde du joueur tombe sous
zro, la partie est termine. La Figure 3.6 montre le jeu en cours dexcution. Mme sil a
t dvelopp rapidement, il rvle les limites des applications de ce type dans un environnement hybride.

iPhone Livre Page 70 Vendredi, 30. octobre 2009 12:04 12

70

Dveloppez des applications pour liPhone

Figure 3.6
Le jeu DollarStash
en cours dexcution.

Comme dautres applications, UIWebView utilise le moteur WebKit de Safari pour afficher
le contenu lcran. Ce moteur, et dautres comme lui, a normment volu ces dernires
annes. Toutefois, lorsque le processeur est fortement sollicit, quelques vnements de
linterface utilisateur, comme les clics et les touchers, sont ignors. Si vous jouez au jeu
DollarStash sur votre appareil, non le simulateur, vous le constaterez rapidement.
Plus le nombre de billets augmente, plus le nombre de touchers ignors par le moteur
augmente. En soumettant lutilisateur un tel dsagrment, vous ne respectez pas une
rgle fondamentale de la conception de linterface utilisateur mentionne dans la premire
section de ce chapitre : la rponse aux actions de lutilisateur doit tre rapide.
Pour les portions fortement interactives des applications de ce type, il est prfrable
dutiliser Objective-C. Cela ne signifie pas que les applications ne puissent pas utiliser
UIWebView pour la mise en page de textes et un affichage simple dimages. Cela signifie
que, jusqu ce que la puissance des processeurs des iPhone et des iPod Touch augmente
significativement, il ne faut pas utiliser les transformations et les animations CSS (Cascading
Style Sheet) natives pour la cration de jeux complexes.
En connaissant les limites de lappareil, il est possible dopter pour une meilleure conception. Si les jeux gourmands en ressources processeur ne sont pas vraiment viables dans des
applications hybrides, lutilisation des transformations et des animations CSS pour raliser
le glisser-dposer, le redimensionnement et la rotation dun seul lment de linterface la
fois est tout fait envisageable.

iPhone Livre Page 71 Vendredi, 30. octobre 2009 12:04 12

Chapitre 3

Interfaces utilisateur

71

Section 5 : crer et utiliser des transformations CSS


personnalises
Cette section explique comment crer des possibilits de glisser-dposer, de redimensionnement et de rotation en se fondant sur les nouvelles transformations CSS intgres au
moteur WebKit. Pour de plus amples informations concernant les transitions, les transformations et les animations CSS, consultez le guide des effets visuels avec Safari ladresse
http://developer.apple.com/safari/library/documentation/InternetWeb/Conceptual/
SafariVisualEffectsProgGuide/Introduction/Introduction.html.
Plusieurs mises en uvre JavaScript du glisser-dposer sont disponibles en tlchargement. Si elles sont parfaitement adaptes une utilisation multinavigateur sur les machines
de bureau, elles sont inefficaces sur les iPhone et les iPod Touch, car elles demandent des
ressources processeur trop importantes. Une bonne alternative consiste employer les
transformations CSS.
WebKit, le moteur utilis par Safari et la classe UIWebView dans les applications hybrides,
est capable de prendre en charge les transitions dfinies en CSS. Elles bnficient en effet
dune acclration matrielle, ce qui les rend plus efficaces que des modifications
programmes en JavaScript comme dans les autres bibliothques.
Prenons comme exemple simple le dcalage vers le bas de la position dune balise HTML
<div>. Dans une version JavaScript classique, il faut modifier lattribut top du style de la
balise. Supposons quune classe CSS soit affecte au <div> et que la valeur de lattribut
top soit gale 50 pixels. Un dcalage vers le bas de 50 pixels supplmentaires sobtient
en fixant ce mme attribut 100 pixels :
unDiv.style.top = 100px;

Cette dclaration est interprte comme une commande JavaScript et elle est excute par
le moteur la mme vitesse et en utilisant les mmes ressources processeur que nimporte
quelle autre commande JavaScript. La transformation CSS quivalente fonctionne diffremment.
En utilisant les transformations CSS pour obtenir ce dcalage de 50 pixels par rapport la
position dorigine dclare, il faut galement employer une dclaration du style pour le
<div>. Toutefois, dans ce cas, nous utilisons un attribut totalement diffrent.
webkitTransform fait partie des nouveaux attributs ajouts aux classes CSS et, par consquent, lattribut style de lobjet JavaScript Element. En lui donnant la bonne valeur, des
fonctions natives bnficiant dune acclration matrielle sont invoques. Puisquil nest

iPhone Livre Page 72 Vendredi, 30. octobre 2009 12:04 12

72

Dveloppez des applications pour liPhone

pas interprt comme du JavaScript, toute modification de lattribut CSS dfini est excute
beaucoup plus rapidement que le code JavaScript quivalent de lexemple prcdent.
La transformation requise ici ne demande quune seule ligne de code :
unDiv.style.webkitTransform = translateY(50px);

premire vue, lattribut de transformation ressemble un pointeur de fonction, comme


onclick, ontouch et dautres gestionnaires dvnements, mais ce nest pas le cas.
La principale diffrence entre webkitTransform et les gestionnaires rside dans le fait
quaucune fonction JavaScript dclare en ligne ou comme une fonction de Window nest
affecte. la place, une chane dcrivant la fonction standard invoquer et ses paramtres
est utilise. Cette chane est ensuite analyse par le moteur WebKit dans une partie de son
code distincte de celle qui interprte les instructions JavaScript.
Notez galement que le dcalage indiqu est relatif lemplacement dorigine du <div>.
Pour dcaler un Element de 50 pixels supplmentaires vers le bas, nous passons translateY le paramtre 50px. Il est galement important de comprendre que la dfinition de
lemplacement initial na pas chang. La valeur dorigine de lattribut top du <div> est
toujours gale 50px. Seul lemplacement auquel il est affich a chang. Si, aprs le
dplacement, vous consultez lattribut top de lobjet, vous obtenez toujours la valeur
50px, non 100px.
Lapplication Drag montre comment mouvoir un <div> sur lcran en utilisant une fonction de dplacement. Pour cela, des gestionnaires ontouchstart, ontouchchange et
ontouchend sont associs au <div> dplac.
Les vnements de toucher diffrent des vnements onclick, onmousedown, onmousemove et onmouseup standard utiliss dans les implmentations JavaScript classiques du
glisser-dposer. Puisquun toucher peut tre constitu de deux touchers individuels, ou
plus, par exemple lorsque lutilisateur pose deux ou trois doigts sur lcran, un vnement
de toucher doit contenir des informations concernant chacun deux.
Chaque toucher individuel et ses informations sont enregistrs dans le tableau targetTouches, qui est un attribut de lobjet event. Ce tableau est dimensionn daprs le
nombre de doigts pos sur llment par lutilisateur. Sa taille est donc gale un
lorsquun doigt est pos, deux, lorsque deux doigts sont utiliss.
Chaque objet enregistr dans le tableau est de type Touch et comprend de nombreux attributs gnralement associs un vnement de la souris en JavaScript. Le Tableau 3.3
recense ces attributs.

iPhone Livre Page 73 Vendredi, 30. octobre 2009 12:04 12

Chapitre 3

Interfaces utilisateur

73

Tableau 3.3 : Attributs de la classe Touch

Attribut

Description

pageX

Le dcalage horizontal partir du bord gauche du document, y compris les informations de


dfilement horizontal

pageY

Le dcalage vertical partir du bord suprieur du document, y compris les informations de dfilement vertical

screenX

Le dcalage horizontal partir du bord gauche de lcran de lappareil

screenY

Le dcalage vertical partir du bord suprieur de lcran de lappareil

clientX

Le dcalage horizontal partir du bord gauche de la fentre de lapplication

clientY

Le dcalage vertical partir du bord suprieur de la fentre de lapplication

target

Lobjet du DOM qui reprsente llment HTML qui a t touch

La mise en uvre du glisser-dposer propose se fonde sur les attributs clientX et


clientY car le dfilement nest pas autoris dans lapplication dexemple. Dans le cas
contraire, il faudrait utiliser les attributs pageX et pageY.
Les lments "sautillants" qui apparaissent lorsque le glisser-dposer dbute posent un
problme. Ce sautillement se produit car lutilisateur a slectionn lobjet en le touchant
quelque part lintrieur de son contour alors que le dplacement est appliqu au coin
suprieur gauche. Si cette discordance nest pas gre, le coin suprieur gauche de lobjet
que lutilisateur fait glisser "saute" lemplacement de son doigt au dbut de lopration.
videmment, lutilisateur considre ce comportement comme anormal. Par exemple, sil
slectionne le centre de lobjet pour dbuter lopration, il peut raisonnablement sattendre
ce que son doigt reste au centre de lobjet pendant lopration. La Figure 3.7 illustre le
fonctionnement de lapplication Drag.
Pour remdier ce problme, lapplication affecte la fonction setStartLocation au
gestionnaire JavaScript ontouchstart. Cette fonction, extraite du fichier main.js et reproduite ci-aprs, obtient et enregistre la position du toucher dorigine, en pixels, par rapport
au coin suprieur gauche de la fentre de lapplication.
1 function setStartLocation(event)
2 {
3
var element = event.target;
4
element.offsetX = event.targetTouches[0].clientX;
5
element.offsetY = event.targetTouches[0].clientY;
6 }

iPhone Livre Page 74 Vendredi, 30. octobre 2009 12:04 12

74

Dveloppez des applications pour liPhone

Figure 3.7
Lapplication Drag aprs
le dplacement du <div>
vert.

En enregistrant cette distance dans les attributs offsetX et offsetY de llment touch,
nous pouvons ensuite lutiliser pendant le dplacement de llment de manire empcher le sautillement. Le dplacement de llment se produit non pas dans la fonction
setStartLocation, mais dans la fonction drag dfinie comme gestionnaire ontouchchange. Cette fonction se trouve galement dans le fichier main.js.
La ligne 3 de la fonction drag donne ci-aprs est indispensable toute mise en uvre du
glisser-dposer pour liPhone et liPod Touch. Normalement, lorsquun vnement de type
modification du toucher est dclench, le navigateur Safari ou UIWebView procde un
dfilement. Pour dsactiver ce comportement standard, nous invoquons la mthode
preventDefault de event. Lorsque cette mthode est invoque dans le gestionnaire
ontouchchange, la vue ne dfile pas si le doigt est dplac dans llment auquel le
gestionnaire est affect.
tant dbarrass du dfilement par dfaut, vous pouvez modifier lemplacement auquel
llment est affich en utilisant webkitTransform. Pour cela, lemplacement du toucher
actuel doit tre obtenu et compar lemplacement du toucher initial enregistr par la
fonction setStartLocation.
1
2
3

function drag(event)
{
event.preventDefault();

iPhone Livre Page 75 Vendredi, 30. octobre 2009 12:04 12

Chapitre 3

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

Interfaces utilisateur

75

var element = event.target;


element.x = event.targetTouches[0].clientX
- event.target.offsetX;
element.y = event.targetTouches[0].clientY
- event.target.offsetY;
if(element.lastX || element.lastY){
element.x += element.lastX;
element.y += element.lastY;
}
element.style.webkitTransform = translate(
+ element.x + px,
+ element.y + px);

Le code des lignes 5 8 calcule les dcalages de la position de llment selon les axes X
et Y. Ces rsultats, en pixels, sont enregistrs dans les attributs x et y de llment courant
en vue de leur utilisation ultrieure, cest--dire aux lignes 13 15 pour modifier laffichage laide de la fonction translate dcrite prcdemment.
Puisquil est possible que ce glisser ne soit pas le premier effectu par lutilisateur sur un
lment, il est ncessaire de conserver les dplacements raliss prcdemment. Le dplacement se fait aux lignes 9 11 du code prcdent et les dcalages sont enregistrs dans la
mthode done ci-aprs, qui est dfinie comme gestionnaire ontouchend.
function done(event)
{
var element = event.target;
element.lastX = element.x;
element.lastY = element.y;
}

La mthode done existe pour une seule raison : enregistrer le dcalage actuel pour le
retrouver si lutilisateur venait dplacer nouveau llment. Pour cela, elle enregistre
les attributs x et y actuels de llment dans les attributs lastX et lastY. Ainsi, nous
sommes certains de pouvoir en disposer chaque dclenchement des vnements ontouchchange lorsque lutilisateur dplace son doigt sur lcran.
En affectant ces trois mthodes en tant que gestionnaires aux lments de linterface, ils
peuvent tre dplacs par lutilisateur de manire simple. la section suivante, vous
verrez comment crer et utiliser un module de glisser-dposer moins naf et plus simple
demploi.
Outre le glisser-dposer, les applications pour liPhone ont souvent besoin dune possibilit de redimensionnement et de rotation des lments de linterface. Ces lments peuvent
tre des <div>, des boutons, des images ou tout autre lment dorganisation ou graphique.

iPhone Livre Page 76 Vendredi, 30. octobre 2009 12:04 12

76

Dveloppez des applications pour liPhone

Le code ncessaire la mise en uvre de ces fonctionnalits est plus court que celui du
glisser-dposer. Il semble vident quApple a voulu que les dveloppeurs incluent ces
comportements dans leurs applications.
Les applications dillustration du traitement des gestes montrent que le redimensionnement et la rotation sont faciles raliser. la place des touchers, elles utilisent des gestes
(gesture). Les gestes diffrent des touchers en cela quils supposent toujours que plusieurs
doigts sont employs, par exemple lors dun pincement.
Pour reprsenter ces gestes, un GestureEvent est pass tout gestionnaire de gestes.
Puisque cette classe reprsente un geste, elle ne comprend aucune information de position
comme la classe TouchEvent. En revanche, elle transmet trois lments dinformation
importants recenss au Tableau 3.4.
Tableau 3.4 : Les attributs importants de GestureEvent

Attribut

Description

scale

Une valeur relle positive ou ngative qui reprsente le changement de la distance


sparant les deux doigts utiliss dans un geste. Les valeurs ngatives indiquent que les
doigts se sont croiss. Cet attribut est utilis dans la gestion du pincement.

rotation

Une valeur relle positive ou ngative qui indique, en degrs, la diffrence angulaire
entre les positions des deux doigts utiliss dans un geste et une ligne verticale.
Cet attribut est utilis dans la gestion des rotations.

target

Lobjet du DOM qui reprsente llment HTML concern par le geste.

Lapplication dillustration du traitement des gestes utilise trois vnements pour redimensionner et faire pivoter un <div>. Pour cela, nous ajoutons au <div> un gestionnaire
ongesturechange nomm changeIt. Pour ajouter des gestionnaires dvnements, utilisez
longlet Comportements de linspecteur. Voici le code de la mthode changeIt :
function changeIt(event)
{
event.preventDefault();
var element = event.target;
element.style.webkitTransform=
rotateZ(+event.rotation
+deg) scale(+event.scale+);
}

iPhone Livre Page 77 Vendredi, 30. octobre 2009 12:04 12

Chapitre 3

Interfaces utilisateur

77

linstar de lapplication Drag, le comportement par dfaut associ lvnement doit


tre dsactiv de manire empcher le dfilement. Mais, contrairement Drag, les informations de rotation et de redimensionnement ne sont pas enregistres. Il est inutile denregistrer les informations de rotation car elles sont relatives une ligne de base, non lobjet
transform.
Les informations de redimensionnement doivent tre enregistres pour tre utilises
lors du geste suivant, car elles sont relatives llment transform et se cumulent.
Cette sauvegarde nest pas effectue dans notre exemple car nous voulons illustrer le
dysfonctionnement correspondant. La section suivante montre comment les enregistrer et
les rutiliser.
Notez que deux fonctions sont employes dans la chane qui dfinit la commande de
webkitTransform. Cela permet deffectuer la rotation et le redimensionnement du <div>
en un seul appel. Rien ne vous empche de les sparer et de les invoquer de manire conditionnelle.
Vous disposez de trois fonctions de rotation pour votre application. Chacune fait pivoter
llment autour de lun des axes du tlphone. Laxe X est horizontal, laxe Y est vertical
et laxe Z sort de lcran. Dans le code prcdent, nous choisissons rotateZ pour que le
<div> pivote sur le plan X-Y de lappareil (voir Figure 3.8).
Figure 3.8
Application de la fonction
rotateZ de webkitTransform.

iPhone Livre Page 78 Vendredi, 30. octobre 2009 12:04 12

78

Dveloppez des applications pour liPhone

Il est trs facile de modifier la faon dont le <div> pivote. En utilisant rotateY, il pivote
selon laxe Y et semble devenir plus troit avant dafficher son verso. Si vous utilisez
rotateX, il pivote le long de laxe X et semble rapetisser avant dafficher son verso.
Vous pourriez penser une mise en uvre de type Cover Flow laide de la rotation. Au
moment de lcriture de ces lignes, elle est dconseille. En effet, le nombre de transformations ncessaires un tel comportement va solliciter normment le processeur de
liPhone ou de liPod Touch et lutilisateur risque dtre du.
Puisque vous connaissez prsent les implmentations naves du glisser-dposer, du redimensionnement et de la rotation, vous tes en mesure de comprendre un module sophistiqu
qui propose ces fonctionnalits.

Section 6 : crer et utiliser un module de glisserdposer, de redimensionnement et de rotation


Tel quil est expliqu au Chapitre 2, les modules sont indpendants et mettent en uvre
lintgralit dune fonctionnalit. Autrement dit, ils sont faiblement coupls au reste du
code dune application et affichent une cohsion forte. Les modules bien conus fournissent toujours une API. Celle que nous allons implmenter dans cette section est dcrite au
Tableau 3.5.
Tableau 3.5 : API de glisser-dposer, redimensionnement et rotation

Fonction

Paramtres

makeDraggable

element (obligatoire) llment du Cette fonction configure les gestionnaires


dvnements sur llment indiqu afin
DOM cible du glissement.
que lutilisateur puisse le faire glisser.
startDragCmd (facultatif) une
commande associe aux fonctions de
contrle invoques la fin de lvnement ontouchstart.
dragCmd (facultatif) une commande
associe aux fonctions de contrle
invoques la fin de tous les vnements ontouchmove.
dropCmd (facultatif) une commande
associe aux fonctions de contrle
invoques la fin de lvnement
ontouchend.

Description

iPhone Livre Page 79 Vendredi, 30. octobre 2009 12:04 12

Chapitre 3

Interfaces utilisateur

79

Tableau 3.5 : API de glisser-dposer, redimensionnement et rotation (suite)

Fonction

Paramtres

Description

makeChangeable

element (obligatoire) llment du Cette fonction configure les gestionnaires


DOM cible du redimensionnement et dvnements sur llment indiqu afin
que lutilisateur puisse le redimensionner
de la rotation.
et le faire pivoter autour de laxe Z.
startChangeCmd (facultatif) une
commande associe aux fonctions de
contrle invoques la fin de lvnement ongesturestart.
dragCmd (facultatif) une commande
associe aux fonctions de contrle
invoques la fin de tous les vnements ongesturechange.
doneChangeCmd (facultatif) une
commande associe aux fonctions de
contrle invoques la fin de lvnement ongestureend.

Dans votre code, vous devez simplement invoquer ces deux fonctions pour que lutilisateur dispose des fonctionnalits de glisser-dposer, de redimensionnement et de rotation
(voir Figure 3.9). Lapplication dragAndGesture se trouve dans le rpertoire Examples du
paquetage QuickConnectiPhone tlcharg. Les fonctions sont dfinies dans le fichier
QCUtilities.js fourni par le framework.
Voici le code de la fonction load dfinie dans le fichier main.js. Il montre comment utiliser
ces fonctions avec des lments de linterface utilisateur.
function load()
{
...
var anElement = document.getElementById(button);
makeDraggable(anElement);
makeChangeable(anElement);
anElement = document.getElementById(imageBox);
makeDraggable(anElement);
makeChangeable(anElement);
anElement = document.getElementById(box);
makeDraggable(anElement);
makeChangeable(anElement);
anElement = document.getElementById(stuff);
makeDraggable(anElement);
}

iPhone Livre Page 80 Vendredi, 30. octobre 2009 12:04 12

80

Dveloppez des applications pour liPhone

Figure 3.9
Lapplication dragAndGesture en cours
dexcution, avec un
lment dplac et pivot.

Dans cet exemple, trois lments de linterface sont modifis afin que lutilisateur puisse
les faire glisser, les redimensionner et les faire pivoter ; le quatrime pourra seulement tre
dplac. Aprs avoir obtenu une rfrence llment de linterface, elle est passe aux
fonctions de lAPI. Cela suffit pour que les lments de linterface utilisateur deviennent
actifs.
Les mises en uvre naves du glisser-dposer, du redimensionnement et de la rotation
dcrites prcdemment dans cette section fonctionnent indpendamment lune de lautre.
Lexemple ci-dessus montre quelles doivent pouvoir oprer de concert. Pour cela, elles
doivent connatre leffet, sil existe, que les autres fonctions ont appliqu llment.
La modification requise commence dans les fonctions makeDraggable et makeChangeable.
La fonction makeDraggable de lAPI prend en charge la configuration et la gestion du
gestionnaire ontouchstart, ainsi que les commandes passes excuter aprs lvnement.
function makeDraggable(anElement, startDragCmd, dragCmd, dropCmd){
anElement.ontouchstart = prepareDrag;
anElement.isDraggable = true;
if(startDragCmd){
anElement.startDragCmd = startDragCmd;
}

iPhone Livre Page 81 Vendredi, 30. octobre 2009 12:04 12

Chapitre 3

Interfaces utilisateur

81

if(dragCmd){
anElement.dragCmd = dragCmd;
}
if(dropCmd){
anElement.dropCmd = dropCmd;
}
}

Vous remarquerez que lattribut isDraggable de llment est fix true. Il sagit de la
premire information que nous devons enregistrer pour que les fonctionnalits puissent
cohabiter. Notez galement quun seul gestionnaire de toucher, ontouchstart, est affect
dans cette fonction. En effet, nous voulons ignorer les touchers lorsquun lment est redimensionn ou pivot ; nous y reviendrons plus loin dans cette section.
La fonction makeChangeable est comparable. Elle affecte les gestionnaires de gestes, fixe
lattribut isChangeable true et enregistre les commandes qui devront tre excutes
aprs lvnement. Contrairement la fonction makeDraggable, elle fixe les gestionnaires
de gestes. En effet, lorsque des vnements de toucher sont dclenchs suite au toucher
simple dun glissement, aucun vnement de geste nest dclench. Si un lment est
dplaable et que le glissement se produise, les vnements de toucher sont dclenchs et
sont traits. Si un lment est modifiable et quun geste se produise, les vnements de
toucher et de geste sont dclenchs, les vnements de toucher sont ignors et les vnements
de geste sont traits.
function makeChangeable(anElement, startChangeCmd, changeCmd, doneChangeCmd){
anElement.ongesturestart = prepareGesture;
anElement.ongesturechange = changeIt;
anElement.ongestureend = gestureDone;
anElement.isChangeable = true;
anElement.oldRotation = 0;
anElement.oldScale = 1;
anElement.startChangeCmd = startChangeCmd;
anElement.changeCmd = changeCmd;
anElement.doneChangeCmd = doneChangeCmd;
}

Deux autres paramtres sont initialiss dans la mthode makeChangeable. Il sagit des
attributs de mmorisation du redimensionnement et de la rotation nomms oldScale et
oldRotation.
Dans lapplication gestures, chaque fois que llment est pivot ou redimensionn, il
commence par reprendre sa taille dorigine, car le redimensionnement effectu prcdemment nest pas mmoris automatiquement. Lattribut oldScale de llment permet de
rsoudre ce problme de taille.

iPhone Livre Page 82 Vendredi, 30. octobre 2009 12:04 12

82

Dveloppez des applications pour liPhone

Lattribut oldScale est initialis 1, car le redimensionnement correspond un multiplicateur appliqu la largeur et la hauteur de llment ; nous y reviendrons plus loin dans
cette section. Si le multiplicateur est suprieur ou gal 0 et infrieur 1, llment est rduit.
Si le multiplicateur est gal 1, llment reste inchang. Si le multiplicateur est suprieur
1, llment est agrandi.
Lorsquun lment a dj t redimensionn, le facteur utilis doit tre combin au
nouveau multiplicateur pour obtenir la taille correcte de llment. Par exemple, si le
premier redimensionnement de llment avait doubl sa taille, la valeur de oldScale doit
tre gale 2. Si lutilisateur pince llment de manire le rduire de 10 %, le nouveau
facteur de redimensionnement doit tre gal 2 0,9, cest--dire 1,8. Si la valeur de
oldScale ntait pas conserve, la taille de llment serait fixe 0,9 et ne correspondrait
pas aux intentions de lutilisateur.
Prcdemment, la fonction prepareDrag tait affecte au gestionnaire dvnements
ontouchstart. Cette fonction, dont le code est donn ci-aprs, contient plusieurs points
intressants. Tout dabord, un tableau dobjets Touch est enregistr. Ainsi, les fonctions de
traitement des vnements de geste peuvent accder aux informations de toucher pertinentes. Par exemple, il peut tre ncessaire de connatre le nombre de touchers qui ont provoqu lvnement de geste. Cette information nest pas disponible dans les vnements
passs aux gestionnaires de gestes.
1 function prepareDrag(event){
2
stopDefault(event);
3
this.touches = event.targetTouches;
4
var self = this;
5
this.timeOut = setTimeout(function(){
6
if(self.changing){
7
return;
8
}
9
self.dragging = true;
10
self.ontouchmove = dragIt;
11
self.ontouchend = dragDone;
12
self.offsetX = event.targetTouches[0].clientX;
13
self.offsetY = event.targetTouches[0].clientY;
14
self.oldZIndex = self.style.zIndex;
15
self.style.zIndex = 50;
16
if(self.startDragCmd){
17
var params = new Array();
18
params.push(event);
19
params.push(self);
20
handleRequest(self.startDragCmd, params);
21
}
22
}, 75);
23 }

iPhone Livre Page 83 Vendredi, 30. octobre 2009 12:04 12

Chapitre 3

Interfaces utilisateur

83

Un autre point intressant du code prcdent se trouve la ligne 5. Au lieu denregistrer


immdiatement la position initiale du toucher dans les attributs offsetX et offsetY de
llment cible du glissement, une minuterie retarde laffectation de ces valeurs et
dautres. Nous procdons ainsi, car la fonction prepareDrag peut avoir t appele suite
un geste effectu par lutilisateur.
Les vnements de toucher dclenchs par des gestes surviennent toujours avant les
vnements de geste dclenchs. Si lvnement pass prepareDrag vient effectivement
dun geste, les gestionnaires ontouchmove et ontouchend ne doivent pas tre fixs pour
viter quils ne soient appels lorsque le geste change et lorsquil se termine. Si ces deux
gestionnaires taient invoqus, ils produiraient un comportement de glissement et provoqueraient un dysfonctionnement du comportement associ au geste.
La minuterie dfinie doit tre suffisamment longue pour que la fonction prepareGesture
gestionnaire du geste soit appele. En effet, elle met jour lattribut changing de
llment en cours de modification.
La ligne 22 montre que le retard est de 75 millisecondes. Cela suffit pour que le gestionnaire de geste soit invoqu et excut si un geste se produit, tout en restant suffisamment
court pour que lutilisateur ne soit pas gn dans le cas dun glissement. Si la minuterie est
trop longue, lutilisateur risque davoir fait glisser son doigt en dehors de llment avant
que celui-ci ne se dplace.
Le dernier point intressant concerne le remplissage du tableau params et lappel
handleRequest. Linvocation de la fonction handleRequest la ligne 20 permet de crer
des fonctions diffres dont lexcution a lieu chaque fois quun vnement de toucher
correspond un glissement. Ces fonctions diffres sont dfinies laide des fonctions
mapCommandTo* fournies dans le fichier mappings.js (voir Chapitre 2). Vous pouvez appeler autant de fonctions de contrle mtier (BCF, Business Control Function) et de fonctions de contrle de laffichage (VCF, View Control Function) que vous le souhaitez
lorsque le glissement dbute. Par exemple, vous pouvez les utiliser pour retirer llment
de son parent, modifier sa couleur darrire-plan ou ses bordures, etc.
Puisque rien nindique comment et si vous utiliserez ces fonctions diffres, certaines
informations sont places dans le tableau param. Comme le montre le code prcdent, ce
tableau comprend llment dplac et lvnement correspondant. Ces informations ne
seront peut-tre pas utiles dans les fonctions diffres que vous allez crer, mais elles sont
votre disposition en cas de besoin.
Lorsque lutilisateur dplace son doigt sur lcran, le gestionnaire dragIt de lvnement
ontouchmove est invoqu de manire rpte. linstar de la fonction drag de lapplication Drag, cette fonction prend en charge le dplacement de llment conformment au

iPhone Livre Page 84 Vendredi, 30. octobre 2009 12:04 12

84

Dveloppez des applications pour liPhone

doigt de lutilisateur. Elle montre lintrt des informations enregistres prcdemment


dans les fonctions gestionnaires de gestes et dans prepareDrag.
Puisque le glisser-dposer se fond sur une transformation, lors dun glissement, toute rotation et tout redimensionnement dj effectus doivent tre appliqus en plus du dplacement. En effet, le webkitTransform du style est rinitialis chacune de ses utilisations.
Si les informations de rotation et de redimensionnement ntaient pas incluses dans la
chane de transformation, llment serait considr dans sa taille et son orientation
dorigine lors du glissement.
Une chane de transformation qui provoque un dplacement, une rotation et un redimensionnement contient plusieurs fonctions et prend laspect suivant :
"translate(-1px, 5px) rotateZ(21deg) scale(0.9)"

Cette instruction dplace llment de un pixel vers la gauche et de cinq pixels vers le bas.
Puis elle pivote llment autour de son axe Z. Enfin, la taille de llment est fixe 90 %
de sa taille dorigine.
Lordre des fonctions est important. Si la rotation se trouve gauche du dplacement dans
la chane, elle se produit avant celui-ci. Par consquent, le dplacement se fait selon un
angle avec les axes X et Y au lieu de se faire le long de ces axes. Le glisser-dposer aurait
un comportement trange, car llment se dplacerait en dcalage du mouvement du
doigt de lutilisateur au lieu de le suivre.
Le code de cration de la chane se trouve aux lignes 13 25. Elles concatnent une souschane une chane qui contient la dclaration de la fonction translate.
1 function dragIt(event){
2
stopDefault(event);
3
4
this.x = event.targetTouches[0].clientX - this.offsetX;
5
this.y = event.targetTouches[0].clientY - this.offsetY;
6
7
if(this.lastX || this.lastY){
8
this.x += this.lastX;
9
this.y += this.lastY;
10
}
11
this.style.webkitTransformOriginX = 50%;
12
this.style.webkitTransformOriginY = 50%;
13
var modStringFragment = ;
14
if(this.isChangeable){
15
if(this.rotation){
16
modStringFragment +=
17
rotateZ(+this.oldRotation+deg);
18
}

iPhone Livre Page 85 Vendredi, 30. octobre 2009 12:04 12

Chapitre 3

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 }

Interfaces utilisateur

85

if(this.oldScale){
modStringFragment +=
scale(+this.oldScale+);
}
}
var modString = translate( + this.x + px,
+ this.y + px)+modStringFragment;
this.style.webkitTransform = modString;
if(this.dragCmd){
var params = new Array();
params.push(event);
params.push(this);
handleRequest(this.dragCmd, params);
}

Les lignes 11 et 12 prsentent un certain intrt. Les attributs webkitTransformOriginX


et webkitTransformOriginY sont fixs leur valeur par dfaut. Comme vous le verrez
plus loin dans cette section, cette opration doit tre effectue dans le cas de tout redimensionnement ou rotation. Sinon, si lutilisateur fait glisser un lment, celui-ci saute et le
doigt ne se trouve pas sur le point de llment touch initialement par lutilisateur.
Lorsque lutilisateur retire son doigt de lcran de lappareil, un vnement ontouchend
est dclench et la fonction gestionnaire dragDone est invoque. Le code suivant, extrait
du fichier QCUtilities.js, montre que son rle est de rinitialiser certains attributs de
llment leur valeur dorigine et denregistrer des informations en vue de leur utilisation
ultrieure.
function dragDone(event){
this.dragging = false;
this.ontouchmove = null;
this.ontouchend = null;
this.lastX = this.x;
this.lastY = this.y;
this.style.zIndex = this.oldZIndex;
if(this.dropCmd){
var params = new Array();
params.push(event);
params.push(this);
handleRequest(this.dropCmd, params);
}
}

iPhone Livre Page 86 Vendredi, 30. octobre 2009 12:04 12

86

Dveloppez des applications pour liPhone

Dans cette fonction, les gestionnaires ontouchmove et ontouchend sont retirs afin
dviter les interfrences avec le traitement du geste. Les coordonnes x et y actuelles de
lvnement sont enregistres et une commande est excute si lune delles est positionne.
Aprs avoir vu lensemble des mthodes sophistiques du glisser-dposer, le traitement
des gestes est plus facile comprendre. Tout comme la prise en charge des gestes peut
affecter le code du glisser-dposer, la gestion du glisser-dposer peut affecter le code de
redimensionnement et de rotation.
La fonction prepareGesture, dont le code donn ci-aprs se trouve dans le fichier QCUtilities.js, est plus simple que la fonction prepareDrag. Elle fixe quelques attributs, mais
elle na pas besoin de retarder certaines oprations, comme nous lavons expliqu prcdemment dans cette section.
function prepareGesture(event){
stopDefault(event);
this.changing = true;
this.oldZIndex = this.style.zIndex;
this.style.zIndex = 50;
if(this.startChangeCmd){
var params = new Array();
params.push(event);
params.push(this);
handleRequest(this.startChangeCmd, params);
}
}

linstar des autres fonctions de prise en charge des vnements de geste, celle-ci
demande au framework dexcuter une commande en invoquant la fonction handleRequest.
Vous pouvez excuter autant de fonctions diffres que vous souhaitez aprs la terminaison du gestionnaire dvnements de geste. Pour de plus amples informations concernant
lassociation de commandes des fonctions, consultez le Chapitre 2.
Lorsque lutilisateur dplace son doigt sur lcran, un vnement ongesturechange est
dclench de manire rpte. Cela conduit linvocation de la fonction changeIt, dont le
code extrait du fichier QCUtilities.js est donn ci-aprs. Cette fonction est responsable du
redimensionnement et de la rotation de llment en fonction de linteraction de lutilisateur
avec lappareil.
Notez quil est possible deffectuer un geste du doigt sur deux lments diffrents ou plus.
En gnral, cela vient dune erreur de lutilisateur et, par consquent, le code doit viter
que les lments ne ragissent lorsquils sont touchs (lignes 5 8).

iPhone Livre Page 87 Vendredi, 30. octobre 2009 12:04 12

Chapitre 3

Interfaces utilisateur

87

Il est galement possible que lutilisateur effectue un pincement qui produit un lment
trop petit pour accepter deux doigts. Si ce comportement tait autoris, lutilisateur ne
pourrait plus redimensionner llment, qui ne serait donc pas modifiable. Les lignes 14
19 vitent que lutilisateur ne rduise trop un lment.
Nous lavons expliqu prcdemment, lordre des dclarations des fonctions dans la
chane de transformation est important. Pour que la rotation et le redimensionnement dun
lment russissent, le dplacement doit se produire en dernier, en le dclarant la fin de
la chane.
"rotateZ(21deg) scale(0.9) translate(-1px, 5px)"

Si le dplacement avait lieu en premier alors que lutilisateur tente de faire pivoter un
lment, celui-ci se dplacerait progressivement au cours de la rotation. Si le dplacement
ntait pas inclus, llment pivoterait autour de son coin suprieur gauche dorigine,
comme dfini dans la classe CSS associe. Ces deux comportements ne sont pas acceptables.
1 function changeIt(event){
2
stopDefault(event);
3
// Lutilisateur peut avoir pos un seul doigt
4
// lintrieur de la cible.
5
if(this.dragging
6
|| (this.touches && this.touches.length < 2)){
7
return;
8
}
9
10
this.rotation = event.rotation;
11
var rotationValue = this.rotation + this.oldRotation;
12
var scaleValue = event.scale * this.oldScale;
13
// Faire en sorte que llment ne soit pas trop petit pour accepter deux
touchers.
14
if(this.offsetWidth * scaleValue < 150){
15
scaleValue = 150/this.offsetWidth;
16
}
17
else if(this.offsetHeight * scaleValue < 150){
18
scaleValue = 150/this.offsetHeight;
19
}
20
this.scale = scaleValue;
21
22
var modString = rotateZ(+rotationValue+
23
deg) scale(+scaleValue+);
24
if(this.lastX || this.lastY){
25
modString += translate( + this.lastX + px,
26
+ this.lastY + px);

iPhone Livre Page 88 Vendredi, 30. octobre 2009 12:04 12

88

Dveloppez des applications pour liPhone

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 }

// Actualiser le centre de rotation.


this.xCenterOffset = 50
+ (this.lastX/this.offsetWidth)
* 100;
this.yCenterOffset = 50
+ (this.lastY/this.offsetHeight)
* 100;
this.style.webkitTransformOriginX =
(this.xCenterOffset)+%;
this.style.webkitTransformOriginY =
this.yCenterOffset)+%;
}
this.style.webkitTransform = modString;
if(this.changeCmd){
var params = new Array();
params.push(event);
params.push(this);
handleRequest(this.changeCmd, params);
}

Les lignes 22 39 crent la chane de transformation et fixent les valeurs de webkitTransformOrigin pour que le redimensionnement et la rotation puissent se produire par
rapport au centre visuel de llment modifi. Les changements dorigine effectus dans le
code prcdent expliquent les rinitialisations ralises dans la mthode dragIt dcrite
prcdemment. Lorigine de la transformation est fixe au milieu de llment, conformment
son dcalage courant par rapport sa position initiale.
Lorsque lutilisateur retire ses doigts de lcran, un vnement ongestureend est dclench et le gestionnaire gestureDone est invoqu. Il est comparable la mthode dragDone,
une exception prs : comme la fonction prepareDrag, il utilise une minuterie.
1 function gestureDone(event){
2
this.style.zIndex = this.oldZIndex;
3
// Lutilisateur na peut-tre pas effectu une rotation.
4
// Dans ce cas, rotation nest pas dfini.
5
if(this.rotation){
6
this.oldRotation += this.rotation;
7
}
8
// Lutilisateur na peut-tre pas effectu un pincement.
9
// Dans ce cas, scale nest pas dfini.
10
if(this.scale){
11
this.oldScale = this.scale;
12
}

iPhone Livre Page 89 Vendredi, 30. octobre 2009 12:04 12

Chapitre 3

13
14
15
16
17
18
19
20
21
22
23
24 }

Interfaces utilisateur

89

if(this.doneChangeCmd){
var params = new Array();
params.push(event);
params.push(this);
handleRequest(this.doneChangeCmd, params);
}
var self = this;
this.timeOut = setTimeout(function(){
self.changing = false;
},75);

Cette minuterie (lignes 21 23) existe pour des raisons semblables celles donnes pour
prepareDrag. Lorsque lvnement ongestureend est dclench, certains vnements de
toucher ne doivent pas tre traits. Si lattribut changing de llment est immdiatement
fix false (ligne 22), alors, daprs le code de prepareDrag vu prcdemment, les
gestionnaires du glissement sont activs.
Si ces gestionnaires du glissement sont activs pour un geste de redimensionnement ou de
rotation, llment saute de manire erratique sur lcran et lexprience de lutilisateur en
est affecte ngativement.
Bien que les comportements de glisser-dposer, de redimensionnement et de rotation doivent
connatre lexistence des uns et des autres, ils doivent tre strictement spars. Dans le cas
contraire, un comportement confus et alatoire de lapplication est possible. Avec le code
prsent dans cette section, extrait du fichier QCUtilities.js, vous disposez dune mise en uvre
cl en main des fonctionnalits de glisser-dposer, de redimensionnement et de rotation.

En rsum
Du point de vue de lutilisateur, linterface de lapplication constitue votre application.
Une mauvaise conception de linterface utilisateur, comme dans le cas du jeu DollarStash,
risque de couler votre application avant que vous ayez lopportunit de lamliorer ou de
la corriger. Nous lavons expliqu dans ce chapitre, une conception avise de linterface
tire parti des trois principes de base suivants :

Ne pas surprendre lutilisateur. Les interactions doivent dclencher les comportements


attendus.

Rendre linterface intuitive. Lutilisateur ne doit pas avoir besoin de lire une documentation pour utiliser lapplication.

Ne pas demander aux appareils plus quils ne peuvent raliser. Les ressources processeur
et mmoire tant limites, elles doivent tre utilises de manire approprie.

iPhone Livre Page 90 Vendredi, 30. octobre 2009 12:04 12

90

Dveloppez des applications pour liPhone

Si vous respectez ces rgles de base et le HIG dApple, votre application aura des chances
de succs beaucoup plus leves. Bien que ces rgles puissent sembler strictes, elles laissent
le champ libre la crativit, comme la montr le module de glisser-dposer, de redimensionnement et de rotation.
Ce module, sil est cr et employ intelligemment, permet damliorer normment
lexprience de lutilisateur avec votre application. En effet, il se fonde sur les possibilits
multitouch de liPhone et de liPod Touch, ainsi que sur le HIG dApple.

iPhone Livre Page 91 Vendredi, 30. octobre 2009 12:04 12

4
GPS, acclromtre et
autres fonctions natives
avec QuickConnectiPhone
LiPhone propose des fonctionnalits uniques que vous pouvez exploiter dans vos applications. Il est notamment possible de faire vibrer le tlphone, de jouer des sons systme,
daccder aux donnes de lacclromtre et de consulter les informations de localisation
GPS. Durant le dveloppement de lapplication, vous pouvez galement crire des messages de dbogage sur la console Xcode. Ces fonctionnalits ne sont pas rserves aux applications crites en Objective-C. Les applications hybrides peuvent les utiliser depuis du
code JavaScript. La premire section de ce chapitre explique comment employer les fonctionnalits natives de liPhone avec lAPI JavaScript de QuickConnect. La deuxime
prsente le code Objective-C qui sous-tend la bibliothque JavaScript QuickConnect.

iPhone Livre Page 92 Vendredi, 30. octobre 2009 12:04 12

92

Dveloppez des applications pour liPhone

Section 1 : activation de lappareil en JavaScript


LiPhone change la donne. Les dveloppeurs dapplications peuvent en effet accder ses
composants matriels, comme lacclromtre. Lexploitation des capacits natives de
liPhone permet de crer des applications innovantes. Leur comportement peut dpendre
des donnes de lacclromtre ou des informations de localisation GPS. Vous pouvez
dcider du moment o le tlphone vibre ou joue certains sons.
Le fichier com.js de QuickConnectiPhone dfinit une fonction qui permet daccder facilement et simplement ces possibilits. Une application invoque makeCall pour envoyer
des requtes au tlphone. Son premier paramtre est une chane de commande, le second
contient les paramtres ncessaires lexcution de la commande, indiqus sous forme
dune chane de caractres. Le Tableau 4.1 recense chaque commande standard, les paramtres correspondants et le comportement obtenu.
Tableau 4.1 : Commandes reconnues par makeCall

Chane de commande

Chane de message

Comportement

logMessage

Les informations afficher sur


la console Xcode.

Le message apparat sur la console Xcode


lexcution du code.

rec

Un fichier audio caf, dont le nom est dfini par la


Une chane JSON qui reprsente un tableau JavaScript dont chane de message, est cr.
le premier lment indique le
nom du fichier audio crer. Le
second lment est start ou
stop selon que vous souhaitez
dmarrer ou arrter lenregistrement des donnes audio.

play

Le fichier audio caf, sil existe, est jou au traUne chane JSON qui reprsente un tableau JavaScript dont vers des haut-parleurs de lappareil ou des couteurs.
le premier lment indique le
nom du fichier audio lire.
Le second lment est start
ou stop selon que vous souhaitez dmarrer ou arrter la
lecture du fichier audio.

loc

Aucune.

Le comportement Core Location de lappareil


est dclench et les informations de latitude, de
longitude et daltitude sont retournes lapplication JavaScript.

playSound

Le tlphone vibre.

iPhone Livre Page 93 Vendredi, 30. octobre 2009 12:04 12

Chapitre 4

GPS, acclromtre et autres fonctions natives avec QuickConnectiPhone

93

Tableau 4.1 : Commandes reconnues par makeCall (suite)

Chane de commande

Chane de message

Comportement

playSound

Le fichier audio laser est jou.

showDate

DateTime.

Le slecteur de date et dheure natif est affich.

showDate

Date.

Le slecteur de date natif est affich.

Lapplication DeviceCatalog comprend un bouton Vibrate qui, lorsque lutilisateur clique


dessus, fait vibrer le tlphone. Le gestionnaire dvnements onclick de ce bouton
est la fonction vibrateDevice prsente ci-aprs. Elle appelle makeCall en lui passant
la commande playSound avec le paramtre 1, ce qui dclenche le vibreur du tlphone. La commande playSound est utilise car liPhone traite les vibrations et les sons
systme brefs comme des sons.
function vibrateDevice(event)
{
// Le paramtre -1 dclenche le vibreur du tlphone.
makeCall("playSound", -1);
}

Puisque le vibreur et les sons systme sont traits de la mme manire, la lecture dun son
systme est quasiment identique au dclenchement du vibreur. Le gestionnaire dvnements onclick du bouton Sound se nomme playSound. Vous le constatez dans le code
suivant, la seule diffrence entre cette fonction et la fonction vibrateDevice se trouve
dans le second paramtre.
function playSound(event)
{
// Le paramtre 0 demande au tlphone dmettre le son dun laser.
makeCall("playSound", 0);
}

Lorsque le second paramtre est 0, le fichier laser.wav inclus dans les ressources du projet
DeviceCatalog est jou en tant que son systme. Les sons systme ne doivent pas durer
plus de 5 secondes et ne sont pas jous comme les autres sons "normaux". Les fichiers
audio plus longs sont lus avec la commande play, que nous examinerons plus loin dans
cette section.
La fonction makeCall employe par les fonctions prcdentes est crite en JavaScript. Elle
est constitue de deux parties. La premire place le message dans une file dattente sil ne
peut pas tre envoy immdiatement. La seconde envoie le message au code Objective-C

iPhone Livre Page 94 Vendredi, 30. octobre 2009 12:04 12

94

Dveloppez des applications pour liPhone

sous-jacent en vue de son traitement. Pour passer le message, une URL inexistante, call,
est affecte la proprit window.location, et les paramtres de la fonction sont prciss
dans lURL.
function makeCall(command, dataString)
{
var messageString = "cmd="+command+"&msg="+dataString;
if(storeMessage ||!canSend){
messages.push(messageString);
}
else{
storeMessage = true;
window.location = "call?"+messageString;
}
}

Avec ce type dURL, un message comprenant lURL et ses paramtres est envoy un
composant Objective-C du framework QuickConnectiPhone. Ce composant interrompt le
chargement de la nouvelle page et passe la commande et le message reus au code de
traitement fourni par le framework. La Section 2 dtaille ce fonctionnement.
Les commandes playSound, logMessage, rec et play sont unidirectionnelles. Autrement
dit, les communications se font depuis JavaScript vers Objective-C, sans que des donnes
ne soient retournes. Les autres commandes unidirectionnelles standard dclenchent la
transmission de donnes depuis les composants Objective-C vers le code JavaScript.
La transmission des donnes au code JavaScript peut se faire de deux manires. La
premire est employe pour passer les informations dacclration dans les coordonnes x,
y et z par un appel la fonction JavaScript handleRequest dcrite au Chapitre 2. Cet
appel utilise la commande accel et les coordonnes x, y et z passes sous forme dun
objet JavaScript depuis les composants Objective-C du framework.
Le fichier mappings.js montre que la commande accel est associe la fonction
displayAccelerationVCF :
mapCommandToVCF(accel, displayAccelerationVCF);

Ainsi, displayAccelerationVCF est appele chaque fois que lacclromtre dtecte un


mouvement. Cette fonction est responsable du traitement de tous les vnements dacclration. Dans lapplication DeviceCatalog, elle place simplement les valeurs x, y et z dans
un lment HTML <div>. Vous devez modifier cette fonction pour exploiter ces valeurs
dans votre application.
La seconde manire de renvoyer des donnes au code JavaScript se fonde sur un appel la
fonction JavaScript handleJSONRequest. Elle fonctionne de manire semblable la fonction

iPhone Livre Page 95 Vendredi, 30. octobre 2009 12:04 12

Chapitre 4

GPS, acclromtre et autres fonctions natives avec QuickConnectiPhone

95

handleRequest dcrite au Chapitre 2, mais elle attend une chane JSON en second paramtre. Cette fonction est une faade pour la fonction handleRequest. Le code suivant
montre quelle convertit simplement la chane JSON indique en un objet JavaScript, puis
passe la commande et le nouvel objet la mthode handleRequest. Cette manire de
transfrer des donnes est utilise pour la demande de localisation GPS initie par un
appel makeCall("loc") et la demande daffichage dun slecteur de date et dheure.
function handleJSONRequest(cmd, parametersString){
var paramsArray = null;
if(parametersString){
var paramsArray = JSON.parse(parametersString);
}
handleRequest(cmd, paramsArray);
}

Dans les deux cas, les donnes rsultantes sont converties en une chane JSON et passes
handleJSONRequest. Pour de plus amples informations concernant le format JSON,
consultez lAnnexe A.
Puisquil existe des bibliothques JSON pour JavaScript et Objective-C, ce format constitue une bonne solution pour changer des informations complexes entre ces deux langages
dans une application. Il est par exemple employ par les gestionnaires onclick pour le
dmarrage et larrt de lenregistrement et de la lecture des fichiers audio.
La fonction playRecording est caractristique des gestionnaires associs aux boutons de
linterface utilisateur qui activent les comportements de lappareil. Lexemple suivant
montre quelle cre un tableau JavaScript, ajoute deux valeurs, convertit le tableau en une
chane JSON et appelle la fonction makeCall avec la commande play.
function playRecording(event)
{
var params = new Array();
params[0] = "recordedFile.caf";
params[1] = "start";
makeCall("play", JSON.stringify(params));
}

Pour stopper la lecture, un appel makeCall avec la commande play est galement effectu, mais le paramtre start est remplac par stop. La fonction terminatePlaying dfinie
dans le fichier main.js met en uvre cette procdure.
Le dmarrage et larrt de lenregistrement dun fichier audio sont cods de manire
semblable playRecording et terminatePlaying, except que la commande play est

iPhone Livre Page 96 Vendredi, 30. octobre 2009 12:04 12

96

Dveloppez des applications pour liPhone

remplace par rec. Puisque le contrle de ces deux fonctionnalits connexes se fait de la
mme faon, il est plus facile dajouter ces comportements dans une application.
Nous lavons vu prcdemment dans cette section, certains comportements de lappareil,
comme le vibreur, ncessitent une communication depuis le code JavaScript vers les
composants Objective-C. Dautres, comme la lecture des coordonnes GPS ou des rsultats dun slecteur, exigent une communication dans les deux directions. La Figure 4.1
prsente lapplication DeviceCatalog qui affiche les informations GPS.
Figure 4.1
Lapplication
DeviceCatalog affiche
les informations GPS.

linstar des exemples unidirectionnels dj prsents, la communication dbute dans le


code JavaScript de lapplication. La fonction getGPSLocation dfinie dans le fichier
main.js initie la communication en appelant makeCall. Notez que dans les exemples
prcdents makeCall ne retourne aucune valeur. Elle utilise un protocole asynchrone pour
communiquer avec le ct Objective-C de la bibliothque, mme lorsque la communication
est bidirectionnelle.
function getGPSLocation(event)
{
document.getElementById(locDisplay).innerText = ;
makeCall("loc");
}

iPhone Livre Page 97 Vendredi, 30. octobre 2009 12:04 12

Chapitre 4

GPS, acclromtre et autres fonctions natives avec QuickConnectiPhone

97

Puisque la communication est asynchrone, comme dans le cas dAJAX, une fonction de
rappel doit tre cre et invoque pour recevoir les informations GPS. Dans le framework
QuickConnectiPhone, cette opration est ralise en associant la commande showLoc
une fonction :
mapCommandToVCF(showLoc, displayLocationVCF);

Dans cet exemple, elle est associe la fonction de contrle de laffichage nomme
displayLocationVCF, qui se contente dafficher la localisation GPS courante dans un
<div>. Bien videmment, les valeurs obtenues peuvent galement servir calculer des
distances, qui seront enregistres dans une base de donnes ou envoyes un serveur
laide de ServerAccessObject, dcrit au Chapitre 8.
function displayLocationVCF(data, paramArray){
document.getElementById(locDisplay).innerText = latitude:
+paramArray[0]+\nlongitude: +paramArray[1]+\naltitude:
+paramArray[2];
}

Laffichage dun slecteur, par exemple le slecteur de date et dheure standard, et la


prsentation de la slection se font de manire semblable lexemple prcdent. La procdure dbute galement par un appel JavaScript au code de gestion de lappareil. Dans ce
cas, la fonction gestionnaire du bouton se nomme showDateSelector ; elle est dfinie
dans le fichier main.js.
function showDateSelector(event)
{
makeCall("showDate", "DateTime");
}

Comme pour les informations GPS, une association doit tre cre. Elle lie la commande
showPickResults la fonction de contrle de laffichage displayPickerSelectionVCF :
mapCommandToVCF(showPickResults, displayPickerSelectionVCF);

La fonction associe la commande insre les rsultats de la slection effectue par lutilisateur dans un simple <div>. Bien videmment, les informations obtenues peuvent tre
employes de nombreuses autres manires.
function displayPickerSelectionVCF(data, paramArray){
document.getElementById(pickerResults).innerHTML = paramArray[0];
}

iPhone Livre Page 98 Vendredi, 30. octobre 2009 12:04 12

98

Dveloppez des applications pour liPhone

Certaines utilisations de makeCall, notamment dans les premiers exemples de cette


section, mettent en place une communication unidirectionnelle entre le code JavaScript et
les composants Objective-C. Celles que nous venons de prsenter emploient une communication bidirectionnelle. Il existe toutefois un autre type de communication unidirectionnelle : de lappareil vers le code JavaScript. Lutilisation des informations de lacclromtre
en est un exemple.
Le gestionnaire Objective-C pour les vnements dacclration (voir Section 2) effectue
directement un appel la fonction JavaScript handleRequest en passant la commande
accel. Cette commande est associe la fonction de contrle de laffichage displayAccelerationVCF :
mapCommandToVCF(accel, displayAccelerationVCF);

linstar des autres VCF, elle place les valeurs dacclration dans un <div>.
function displayAccelerationVCF(data, param){
document.getElementById(accelDisplay).innerText =x:
+param.x+\ny: +param.y+\nz: +param.z;
}

la diffrence des autres fonctions, elle reoit dans son paramtre param non pas un
tableau mais un objet. La Section 2 montre comment cet objet est cr partir des informations venant du gestionnaire Objective-C des vnements dacclration.
Cette section a expliqu comment ajouter aux applications JavaScript les fonctionnalits
de liPhone les plus demandes. La Section 2 dcrit les parties Objective-C du framework
qui le permettent.

Section 2 : activation de lappareil en Objective-C


Cette section suppose que vous matrisiez Objective-C et que vous sachiez comment
lutiliser pour crer des applications pour liPhone. Si ce nest pas le cas, lisez louvrage
The iPhone Developers Cookbook, dErica Sadun. Si vous souhaitez uniquement utiliser
le framework QuickConnectiPhone pour dvelopper des applications JavaScript pour
liPhone, vous ntes pas oblig de lire cette section.
Faire vibrer liPhone avec du code Objective-C est lun des comportements les plus
simples raliser. Si vous incluez le framework AudioToolbox dans les ressources du
projet, la ligne suivante suffit :
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);

iPhone Livre Page 99 Vendredi, 30. octobre 2009 12:04 12

Chapitre 4

GPS, acclromtre et autres fonctions natives avec QuickConnectiPhone

99

La question qui se pose alors est : "Comment puis-je faire en sorte que la fonction AudioServicesPlaySystemSound soit appele lorsque le code modifie lattribut location de
UIWebView ?"
La classe QuickConnectViewController implmente la mthode dlgue shouldStartLoadWithRequest. Puisque QuickConnectViewController est le dlgu du
UIWebView embarqu, nomm aWebView, cette mthode est invoque chaque fois que le
UIWebView embarqu voit son attribut location modifi. Le code suivant, ainsi que la
ligne 90 du fichier QuickConnectViewController.m, montre laffectation de ce dlgu :
[aWebView setDelegate:self];

Le comportement de base de la fonction shouldStartLoadWithRequest est simple. Sa


conception vous permet de dcider si la nouvelle page demande doit tre rellement charge. Le framework se fonde sur cette facult pour interdire le chargement de la page lors
des requtes effectues par les appels JavaScript dcrits la Section 1 et pour excuter un
autre code Objective-C.
La mthode shouldStartLoadWithRequest prend plusieurs paramtres :

curWebView. Le UIWebView qui contient lapplication JavaScript.

request. Un NSURLRequest qui contient, entre autres, la nouvelle URL.

navigationType. Un UIWebViewNavigationType qui peut tre utilis pour dterminer si la requte est le rsultat dun clic sur un lien ou si elle a t gnre suite une
autre action.
-(BOOL)webView:(UIWebView *)curWebView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType

LURL compose par la fonction JavaScript makeCall pour faire vibrer le tlphone,
call?cmd=playSound&msg=-1, est contenue dans lobjet request et peut tre facilement
retrouve sous forme dune chane de caractres en envoyant le message URL cet objet.
Ce message retourne un objet de type NSURL, auquel est ensuite pass le message absoluteString. Nous obtenons ainsi un pointeur NSString qui reprsente lURL. Cette chane,
enregistre dans la variable url, peut tre dcompose dans un tableau, en utilisant le
point dinterrogation (?) comme caractre de sparation. Le tableau rsultant contient des
pointeurs NSString.
NSString *url = [[request URL] absoluteString];
NSArray *urlArray = [url componentsSeparatedByString:@"?"];

iPhone Livre Page 100 Vendredi, 30. octobre 2009 12:04 12

100

Dveloppez des applications pour liPhone

urlArray contient deux lments. Le premier correspond la partie call de lURL,


tandis que le second est la chane de commande cmd=playSound&msg=-1. Pour dterminer
la commande et ses paramtres, dans ce cas 1, nous devons poursuivre lanalyse de la
chane de commande. Pour cela, commandString est dcompose en fonction du caractre
& dans le tableau nomm urlParamsArray.
NSString *commandString = [urlArray objectAtIndex:1];
NSArray *urlParamsArray = [commandString componentsSeparatedByString:@"&"];
// La commande est le premier paramtre dans lURL.
cmd = [[[urlParamsArray objectAtIndex:0]
componentsSeparatedByString:@"="] objectAtIndex:1];

Dans notre exemple, demander au tlphone de vibrer, le premier lment du tableau


urlParamsArray est cmd=playSound et le second est msg=-1. Ainsi, en dcoupant les
lments de urlParamsArray avec le caractre = comme dlimiteur, nous pouvons obtenir
la commande excuter et son paramtre.
Les lignes 1 3 du code suivant enregistrent le paramtre pass dans lURL en tant que
valeur associe la cl msg dans la variable parameterArrayString de type NSString.
Puisque le code JavaScript qui a compos lURL convertit toutes ses composantes au
format JSON, ce NSString est un objet qui a t converti dans ce format. Cela inclut des
nombres, comme dans notre exemple, des chanes de caractres, des tableaux et dautres
paramtres passs depuis JavaScript. Par ailleurs, si des espaces ou dautres caractres
spciaux apparaissent dans les donnes, UIWebView leur applique lchappement dans
lURL. Cest pourquoi les lignes 6 8 suppriment lchappement sur ces caractres
spciaux dans la chane JSON.
1 NSString *parameterArrayString = [[[urlParamsArray
2

objectAtIndex:1] componentsSeparatedByString:@"="]

objectAtIndex:1];

4 // Retirer tout encodage ajout, comme lchappement des caractres


5 // effectu dans lURL par UIWebView.
6 parameterArrayString = [parameterArrayString
7

stringByReplacingPercentEscapesUsingEncoding:

NSASCIIStringEncoding];

9 SBJSON *generator = [SBJSON alloc];


10 NSError *error;
11 paramsToPass = [[NSMutableArray alloc]
12

initWithArray:[generator

13

objectWithString:parameterArrayString

14

error:&error]];

iPhone Livre Page 101 Vendredi, 30. octobre 2009 12:04 12

Chapitre 4

GPS, acclromtre et autres fonctions natives avec QuickConnectiPhone

101

15 if([paramsToPass count] == 0){


16
// Si aucun tableau de donnes nest envoy, une chane a d tre passe
17
// comme seul paramtre.
18
[paramsToPass addObject:parameterArrayString];
19 }
20 [generator release];

Les lignes 9 14 convertissent la chane JSON parameterArrayString en un objet


Objective-C NSArray natif. La ligne 9 instancie un objet generator de type SBJSON,
auquel le message objectWithString est ensuite envoy :
- (id)objectWithString:(NSString*)jsonrep error:(NSError**)error;

Ce message en plusieurs parties comprend une chane JSON, dans ce cas parameterArrayString, et un pointeur error de type NSError. Lorsquune erreur se produit au
cours du processus de conversion, le pointeur error est affect, sinon il vaut nil.
Dans ce cas, la valeur de retour de ce message est 1. Si un tableau JavaScript est converti
en chane, la valeur de retour est un pointeur NSArray, ou, dans le cas dune chane JavaScript, il sagit dun pointeur NSString. Lorsquun objet JavaScript de type personnalis
est pass, lobjet retourn est un pointeur NSDictionary.
ce stade, puisque nous disposons de la commande et de ses paramtres, il est possible
dutiliser une instruction if ou case pour effectuer lopration demande. Toutefois, ces
instructions conditionnelles ne constituent pas la solution optimale car elles doivent tre
modifies chaque fois quune commande est ajoute ou retire. Au Chapitre 2, un
problme comparable a t rsolu dans la partie JavaScript de QuickConnectiPhone en
mettant en place une fonction contrleur frontal, nomme handleRequest, qui contient
des appels aux implmentations des contrleurs dapplication. Puisque le problme est
identique ici, une version Objective-C de handleRequest doit permettre de le rsoudre.
La Section 3 sintresse la mise en uvre des contrleurs frontaux et des contrleurs
dapplication en Objective-C. La ligne de code suivante obtient une instance de lobjet
QuickConnect et lui passe le message handleRequest withParameters. Aucune autre
opration nest ncessaire dans la mthode dlgue shouldStartLoadWithRequest.
[[QuickConnect getInstance] handleRequest:cmd withParameters:paramsToPass];

Puisque nous utilisons le message handleRequest des objets QuickConnect, nous avons
besoin dun mcanisme pour lier les commandes la fonctionnalit requise, la manire
du Chapitre 2 en JavaScript. Lobjet QCCommandMappings, dclar dans les fichiers
QCCommandMappings.m et .h du groupe QCObjC, contient toutes les associations pour les
objets de contrle mtier (BCO, Business Control Object) et les objets de contrle de
laffichage (VCO, View Control Object) de cet exemple.

iPhone Livre Page 102 Vendredi, 30. octobre 2009 12:04 12

102

Dveloppez des applications pour liPhone

Le code suivant correspond la mthode mapCommands de lobjet QCCommandMappings


qui est invoque au dmarrage de lapplication. Elle reoit limplmentation dun contrleur dapplication, qui cre les associations entre les commandes et les fonctionnalits. La
Section 3 expliquera le code du message mapCommandToVCO et de lappel mapCommands.
1
2
3
4
5
6
7

+ (void) mapCommands:(QCAppController*)aController{
[aController mapCommandToVCO:@"logMessage" withFunction:@"LoggingVCO"];
[aController mapCommandToVCO:@"playSound" withFunction:@"PlaySoundVCO"];
[aController mapCommandToBCO:@"loc" withFunction:@"LocationBCO"];
[aController mapCommandToVCO:@"sendloc" withFunction:@"LocationVCO"];
[aController mapCommandToVCO:@"showDate" withFunction:@"DatePickerVCO"];
[aController mapCommandToVCO:@"sendPickResults" withFunctio n:@"PickResultsVCO"];
8
[aController mapCommandToVCO:@"play" withFunction:@"PlayAudioVCO"];
9
[aController mapCommandToVCO:@"rec" withFunction:@"RecordAudioVCO"];
10 }

La ligne 3 du code prcdent est en rapport avec le dclenchement du vibreur. Nous


lavons vu prcdemment dans cette section, la commande reue depuis la partie JavaScript de lapplication se nomme playSound. En passant cette commande en premier
paramtre du message mapCommandToVCO et PlaySoundVCO comme paramtre de la
seconde partie, withFunction, nous crons un lien qui conduit le contrleur dapplication
envoyer un message doCommand avec le paramtre 1 la classe PlaySoundVCO. Vous le
constatez, toutes les autres commandes de lexemple DeviceCatalog envoyes depuis
JavaScript sont associes dans cette fonction.
Le code de PlaySoundVCO laquelle la commande playSound est associe se trouve dans
les fichiers PlaySoundVCO.m et PlaySoundVCO.h. La mthode doCommand prend en
charge tous les comportements de lobjet.
Pour jouer un son systme, un son prdfini (seule la vibration est dfinie au moment de
lcriture de ces lignes) doit tre utilis ou un son systme doit tre gnr partir dun
fichier audio. La mthode doCommand de la classe PlaySoundVCO illustre ces deux fonctionnements.
1
2
3
4
5
6
7
8
9

+ (id) doCommand:(NSArray*) parameters{


SystemSoundID aSound =
[((NSNumber*)[parameters objectAtIndex:1]) intValue];
if(aSound == -1){
aSound = kSystemSoundID_Vibrate;
}
else{
NSString *soundFile =
[[NSBundle mainBundle] pathForResource:@"laser"

iPhone Livre Page 103 Vendredi, 30. octobre 2009 12:04 12

Chapitre 4

10
11
12
13
14
15
16
17
18
19 }

GPS, acclromtre et autres fonctions natives avec QuickConnectiPhone

103

ofType:@"wav"];
NSURL *url = [NSURL fileURLWithPath:soundFile];
// Si la lecture du fichier audio est trop longue,
// nous recevons une erreur -1500.
OSStatus error = AudioServicesCreateSystemSoundID(
(CFURLRef) url, &aSound );
}
AudioServicesPlaySystemSound(aSound);
return nil;

Vous pouvez le voir la ligne 4 de lexemple prcdent, si le paramtre dindice 1 a la


valeur 1, la variable SystemSoundID aSound est fixe la valeur prdfinie
kSystemSoundID_Vibrate. Sinon un son systme est cr partir du fichier laser.wav qui
se trouve dans le groupe Resources de lapplication et un identifiant gnr pour ce
nouveau son est affect la variable aSound.
Dans tous les cas, la fonction C AudioServicesPlaySystemSound est appele, le son est
jou ou lappareil vibre. Si lappareil est un iPod Touch, les demandes de vibration sont
ignores. Dans une application relle qui dispose de plusieurs sons, il est facile dtendre
cette fonction en passant dautres nombres dsignant les sons jouer.
Puisque SystemSoundID est de type numrique, les sons systme doivent tre gnrs au
dbut de lapplication et leurs identifiants doivent tre passs la partie JavaScript de
lapplication en vue dune utilisation ultrieure. Cela vite la charge ncessaire la cration du son systme chaque fois quil doit tre jou et, par consquent, lutilisateur ne
constate aucun retard dans la lecture du son.
Puisque nous connaissons prsent la procdure qui permet de passer des commandes
depuis JavaScript Objective-C et la manire de faire vibrer lappareil ou de jouer un son
bref, il est facile de comprendre le passage dune commande Objective-C et le retour des
rsultats la partie JavaScript de lapplication.
En raison de la similitude de ces communications, la dtection de la localisation GPS, trs
utilise dans les applications pour liPhone, nous servira dexemple. Elle se fonde sur les
possibilits de communication bidirectionnelle entre JavaScript et Objective-C apportes
par le framework QuickConnectiPhone.
linstar de la gestion des commandes envoyes depuis le framework JavaScript, nous
avons besoin dun mcanisme pour lier la commande loc et ainsi pouvoir obtenir les
donnes et la rponse renvoyes.
[aController mapCommandToBCO:@"loc" withFunction:@"LocationBCO"];
[aController mapCommandToVCO:@"sendloc" withFunction:@"LocationVCO"];

iPhone Livre Page 104 Vendredi, 30. octobre 2009 12:04 12

104

Dveloppez des applications pour liPhone

Dans ce cas, il existe deux associations : la premire avec un BCO, la seconde avec un
VCO. linstar des BCF et VCF vues au Chapitre 2, les BCO permettent dobtenir les
donnes, les VCO, de les afficher.
Puisque les BCO dune commande donne sont excuts par le framework QuickConnectiPhone avant tous les VCO, un message doCommand est tout dabord envoy la classe
LocationBCO de manire obtenir et retourner les donnes GPS. La mthode doCommand
suivante appartient la classe LocationBCO. Elle effectue les appels permettant lappareil
de dterminer sa localisation GPS.
+ (id) doCommand:(NSArray*) parameters{
QuickConnectViewController *controller =
(QuickConnectViewController*)[parameters objectAtIndex:0];
[[controller locationManager] startUpdatingLocation];
return nil;
}

Cette mthode sollicite le matriel de localisation GPS en obtenant le premier lment du


tableau pass en paramtre la mthode et en lui demandant dactiver le matriel. Le
framework fixe toujours le premier paramtre QuickConnectViewController afin que
les BCO ou les VCO associs aux commandes puissent sen servir en cas de besoin. Dans
tous les BCO et VCO Objective-C, les paramtres provenant de JavaScript dbutent
lindice 1.
Lobjet QuickConnectViewController comprend un attribut CLLocationManager, nomm
locationManager, qui est activ et dsactiv en fonction de lapplication. Il est important que
ce gestionnaire ne sexcute pas plus longtemps que ncessaire car il consomme beaucoup
dnergie de la batterie. Par consquent, le code prcdent active le dispositif de localisation en lui envoyant un message startUpdatingLocation chaque fois que les informations
sont demandes. Le dispositif est dsactiv ds que la localisation est dtermine.
Les objets CLLocationManager se comportent de manire asynchrone. Autrement dit,
lorsquune demande de localisation est effectue, une fonction de rappel prdfinie est
invoque aprs leur obtention. Cette fonction prdfinie permet daccder au gestionnaire
de localisation et deux localisations : une localisation prcdemment dtermine et la
localisation actuelle.
Le gestionnaire de localisation affine progressivement la localisation de lappareil. Au
cours de cette procdure, il appelle plusieurs fois didUpdateToLocation. Lexemple de
code suivant calcule le temps ncessaire dterminer la nouvelle localisation. La ligne 9
vrifie sil est infrieur cinq secondes et, dans laffirmative, poursuit la localisation.
1
2

(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation

iPhone Livre Page 105 Vendredi, 30. octobre 2009 12:04 12

Chapitre 4

GPS, acclromtre et autres fonctions natives avec QuickConnectiPhone

3
4 {
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 }

105

fromLocation:(CLLocation *)oldLocation
// Si lvnement est relativement rcent, dsactiver les actualisations
pour conomiser la batterie.
NSDate* eventDate = newLocation.timestamp;
NSTimeInterval howRecent =
[eventDate timeIntervalSinceNow];
if (abs(howRecent) < 5.0){
[manager stopUpdatingLocation];
NSMutableArray *paramsToPass =
[[NSMutableArray alloc] initWithCapacity:2];
[paramsToPass addObject:self];
[paramsToPass addObject:newLocation];
[[QuickConnect getInstance]
handleRequest:@"sendloc"
withParameters:paramsToPass];
}
// Sinon, ignorer lvnement et passer au suivant.

Aprs avoir termin la localisation, le code envoie un message la classe contrleur frontal de QuickConnect en lui indiquant quelle doit traiter une requte sendloc avec QuickConnectViewController, self et la nouvelle localisation passe en paramtre supplmentaire.
La commande sendloc est associe au gestionnaire LocationVCO dont la mthode
doCommand est reproduite ci-aprs. Cette mthode obtient le UIWebView nomm webView
partir du QuickConnectViewController qui a demand initialement les informations
de localisation GPS. Ces informations sont ensuite places dans le NSArray nomm
passingArray.
Pour retourner les informations GPS lobjet webView, le NSArray qui les contient doit
tre converti en une chane JSON. La classe SBJSON, dj employe prcdemment pour
crer un tableau partir dune chane JSON, est prsent utilise pour crer un NSString
partir du NSArray (lignes 21 et 22).
1
2
3
4
5
6
7
8
9

+ (id) doCommand:(NSArray*) parameters{


QuickConnectViewController *controller =
(QuickConnectViewController*)[parameters
objectAtIndex:0];
UIWebView *webView = [controller webView];
CLLocation *location = (CLLocation*)[parameters
objectAtIndex:1];
NSMutableArray *passingArray = [[NSMutableArray alloc]

iPhone Livre Page 106 Vendredi, 30. octobre 2009 12:04 12

106

Dveloppez des applications pour liPhone

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

initWithCapacity:3];
[passingArray addObject: [NSNumber numberWithDouble:
location.coordinate.latitude]];
[passingArray addObject: [NSNumber numberWithDouble:
location.coordinate.longitude]];
[passingArray addObject: [NSNumber numberWithFloat:
location.altitude]];
SBJSON *generator = [SBJSON alloc];
NSError *error;
NSString *paramsToPass = [generator
stringWithObject:passingArray error:&error];
[generator release];
NSString *jsString = [[NSString alloc]
initWithFormat:@"handleJSONRequest(showLoc, %@)",
paramsToPass];
[webView
stringByEvaluatingJavaScriptFromString:jsString];
return nil;

Aprs avoir converti les informations de localisation GPS en une chane JSON qui reprsente un tableau de nombre, un appel au moteur JavaScript est effectu depuis lobjet
webView. Pour cela, nous commenons par crer un NSString qui contient le code JavaScript excuter. Dans cet exemple, il sagit de handleJSONRequest, avec showLoc pour
commande et les informations GPS au format JSON comme chane. Nous lavons vu la
Section 1, cette requte fait apparatre les donnes GPS dans un <div> de la page HTML
affiche.
Ayant prsent tudi cet exemple, vous pouvez examiner DatePickerVCO et PickResultsVCO dans lapplication DeviceCatalog et voir comment cette mme approche est employe
pour afficher les slecteurs de date et dheure standard disponibles en Objective-C. Mme
si des slecteurs prdfinis sont disponibles en JavaScript dans UIWebView, ils ne sont pas
aussi jolis que ceux fournis par Objective-C. En utilisant les slecteurs standard et ceux
que vous pourriez dfinir, lexprience de lutilisateur avec votre application hybride nen
sera que meilleure.

iPhone Livre Page 107 Vendredi, 30. octobre 2009 12:04 12

Chapitre 4

GPS, acclromtre et autres fonctions natives avec QuickConnectiPhone

107

Section 3 : implmentation Objective-C


de larchitecture de QuickConnectiPhone
Le code prsent aux Sections 1 et 2 dpend normment de limplmentation en Objective-C de larchitecture explique au Chapitre 2. Cette section dcrit cette implmentation.
Pour une explication complte de chaque composant, consultez le Chapitre 2, qui sintresse limplmentation JavaScript.
linstar de limplmentation JavaScript, toutes les demandes de comportement applicatif
se font au travers dun contrleur frontal. Celui-ci est mis en uvre par la classe QuickConnect, dont le code source se trouve dans les fichiers QuickConnect.m et QuickConnect.h.
Puisque les messages envoys QuickConnect peuvent provenir de diffrents endroits de
lapplication, cette classe est un singleton.
Les classes singletons sont crites de manire quune seule instance de la classe soit
alloue dans une application. Lorsquelles sont bien implmentes, il existe toujours un
moyen dobtenir un pointeur sur cet objet unique depuis nimporte quel point de lapplication. Avec lobjet singleton QuickConnect, cela se fait au travers de la mthode de classe
getInstance, qui retourne lunique instance de QuickConnect alloue lors de la premire
invocation de cette mthode.
Puisquil sagit dune mthode de classe, un message getInstance peut tre envoy la
classe sans instancier un objet QuickConnect. Son invocation retourne un pointeur sur
linstance de QuickConnect alloue. Le code suivant montre que cette opration est ralise en affectant une instance de la classe un pointeur QuickConnect dfini de manire
statique.
+ (QuickConnect*)getInstance{
// Puisque cette ligne est dclare avec static,
// elle est excute une seule fois.
static QuickConnect *mySelfQC = nil;
@synchronized([QuickConnect class]) {
if (mySelfQC == nil) {
mySelfQC = [QuickConnect singleton];
[mySelfQC init];
}
}
return mySelfQC;
}

Le message singleton envoy avant init utilise le comportement dfini dans la superclasse FTSWAbstractSingleton de lobjet QuickConnect. Cette superclasse met en

iPhone Livre Page 108 Vendredi, 30. octobre 2009 12:04 12

108

Dveloppez des applications pour liPhone

uvre le comportement de singleton, comme redfinir les mthodes new, clone et dautres
que le programmeur pourrait utiliser par erreur pour allouer une autre instance de QuickConnect. Cest pourquoi seule la mthode getInstance est en mesure de crer et dutiliser
un objet QuickConnect. linstar de tous les objets bien crits en Objective-C, aprs son
allocation, lobjet QuickConnect doit tre initialis.
Lallocation et linitiation de lobjet ont lieu uniquement si aucun objet QuickConnect na
t affect lattribut mySelfQC. Par ailleurs, en raison de la synchronisation du contrle
de lexistence de lobjet QuickConnect instanci, ces oprations sont sres vis--vis des
threads.
- (void) handleRequest: (NSString*) aCmd withParameters:(NSArray*) parameters est une autre mthode de la classe QuickConnect. De mme que la fonction
JavaScript handleRequest(aCmd, parameters) du Chapitre 2, elle reprsente le mcanisme permettant dexcuter dans votre application la fonctionnalit demande.
Une chane de commande et un tableau de paramtres sont passs la mthode. Dans
lexemple suivant, les lignes 3 9 montrent quune suite de messages est envoye au
contrleur dapplication. Les lignes 3 et 4 commencent par excuter les VCO associs la
commande. Si la commande et les paramtres passent avec succs la validation, les BCO
associs la commande sont excuts via un message dispatchToBCO. Ce message
retourne un NSMutableArray qui contient les donnes du tableau parameters dorigine,
auxquelles ont t ajoutes celles accumules au cours des invocations des BCO.
1 - (void) handleRequest: (NSString*) aCmd
2
withParameters:(NSArray*) parameters{
3
if([self->theAppController dispatchToValCO:aCmd
4
withParameters:parameters]!= nil){
5
NSMutableArray *newParameters =
6
[self->theAppController dispatchToBCO:aCmd
7
withParameters:parameters];
8
[self->theAppController dispatchToVCO:aCmd
9
withParameters:newParameters];
10
}
11 }

Lorsque lappel dispatchToBCO:withParameters est termin, un message dispatchToVCO:withParameters est envoy. Les VCO associs la commande indique sont alors
excuts.
En utilisant la mthode handleRequest:withParameters pour toutes les demandes de
fonctionnalits, chaque requte passe par le processus en trois tapes suivant :

validation ;

iPhone Livre Page 109 Vendredi, 30. octobre 2009 12:04 12

Chapitre 4

GPS, acclromtre et autres fonctions natives avec QuickConnectiPhone

excution des rgles mtier (BCO) ;

excution des modifications de laffichage (VCO).

109

Comme dans limplmentation JavaScript, chaque mthode dispatchTo est une faade.
Dans ce cas, la mthode Objective-C sous-jacente est dispatchToCO:withParameters.
Cette mthode commence par obtenir tous les objets de commande associs la
commande default partir du paramtre aMap. Il contient des BCO, des VCO ou des
ValCO, selon la mthode faade invoque. Ces objets de commande par dfaut, sils existent, sont obtenus et utiliss pour toutes les commandes. Si vous souhaitez que certains
objets de commande soient employs avec toutes les commandes, il est inutile de les associer tous chaque commande individuelle. Il suffit de les associer une fois la commande
default.
Pour utiliser les objets de commandes obtenus, un message doCommand doit leur tre
envoy. Les lignes 19 23 de lexemple suivant montre ce message obtenu comme un
slecteur et le passage du message performSelector. Cela dclenche lexcution du
message doCommand que vous avez implment dans votre QCCommandObject.
1 - (id) dispatchToCO: (NSString*)command withParameters:
2
(NSArray*)parameters andMap:(NSDictionary*)aMap{
3
// Crer un tableau modifiable qui contient tous
4
// les paramtres existants.
5
NSMutableArray *resultArray;
6
if(parameters == nil){
7
resultArray = [[NSMutableArray alloc]
8
initWithCapacity:0];
9
}
10
else{
11
resultArray = [NSMutableArray
12
arrayWithArray:parameters];
13
}
14
// Affecter quelque chose result afin que
15
// lexcution se poursuive mme sil nexiste
16
// aucune association.
17
id result = @"Continue";
18
if([aMap objectForKey:@"default"]!= nil){
19
SEL aSelector = @selector(doCommand);
20
while((result = [((QCCommandObject*)
21
[aMap objectForKey:@"default"])
22
performSelector:aSelector
23
withObject:parameters])!= nil){

iPhone Livre Page 110 Vendredi, 30. octobre 2009 12:04 12

110

Dveloppez des applications pour liPhone

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 }

if(aMap == self->businessMap){
[resultArray addObject:result];
}
}
}
// Si tous les appels de mthode des objets de commande par dfaut
// retournent une valeur, excuter les objets personnaliss.
if(result!= nil && [aMap objectForKey:command]!=
nil){
NSArray *theCommandObjects =
[aMap objectForKey:command];
int numCommandObjects = [theCommandObjects count];
for(int i = 0; i < numCommandObjects; i++){
QCCommandObject *theCommand =
[theCommandObjects objectAtIndex:i];
result = [theCommand doCommand:parameters];
if(result == nil){
resultArray = nil;
break;
}
if(aMap == self->businessMap){
[resultArray addObject:result];
}
}
}
if(aMap == self->businessMap){
return resultArray;
}
return result;

Aprs lenvoi des messages doCommand tous les QCCommandObject associs la


commande default, la mme opration est effectue pour les QCCommandObject que vous
avez associs la commande passe en paramtre la mthode. Lexistence de ces QCCommandObject se justifie de la mme faon que les fonctions de contrle dans limplmentation JavaScript. Puisque les QCCommandObject contiennent le code du comportement de
lapplication, un exemple permettra de mieux comprendre leur cration.
Puisque QCCommandObject est la classe mre de LoggingVCO, celle-ci doit implmenter la
mthode doCommand. Lintgralit du contenu du fichier LoggingVCO.m de lapplication
DeviceCatalog est donne ci-aprs. Sa mthode doCommand crit dans le journal de lapplication en cours dexcution. Ce VCO journalise les messages de dbogage gnrs par le
code JavaScript de lapplication. La Figure 4.2 prsente les appels requis.

iPhone Livre Page 111 Vendredi, 30. octobre 2009 12:04 12

Chapitre 4

GPS, acclromtre et autres fonctions natives avec QuickConnectiPhone

111

Figure 4.2
Ce diagramme de squence montre les mthodes Objective-C invoques pour traiter une requte de journalisation dun message de dbogage JavaScript.

La mthode doCommand de la classe LoggingVCO est courte. Toutes les mthodes doCommand des diffrents types dobjets de commande doivent toujours tre brves. Elles
doivent faire une seule chose et la faire bien. Si vous constatez que la mthode doCommand en
cours de dveloppement devient longue, vous devez envisager son dcoupage en composants
logiques et la cration de plusieurs classes dobjets de commande. En effet, lorsque ces
mthodes deviennent longues, il est probable quelles font plus dune chose.
Dans lexemple suivant, LoggingVCO soccupe uniquement de la journalisation des messages sur la console de dbogage de Xcode. Bien videmment, ce petit composant peut tre
rutilis avec de nombreuses commandes et dautres objets de commande.
Le comportement de ce VCO est mis en uvre par une seule ligne qui excute la fonction
NSLog. Le premier objet du tableau parameters est concatn une chane statique et affich.
#import "LoggingVCO.h"
@implementation LoggingVCO
+ (id) doCommand:(NSArray*) parameters{
NSLog(@"JavaScriptMessage: %@",
[parameters objectAtIndex:1]);
return nil;
}
@end

Pour que la journalisation soit effective, il faut une association entre la commande
logMessage et la classe LoggingVCO. Comme dans limplmentation JavaScript, cette
association se fait en ajoutant logMessage, en tant que cl, et le nom de la classe LoggingVCO,

iPhone Livre Page 112 Vendredi, 30. octobre 2009 12:04 12

112

Dveloppez des applications pour liPhone

en tant que valeur, une mappe. Le code suivant, tir du fichier QCCommandMappings.m
de lapplication DeviceCatalog, associe logMessage la classe LoggingVCO.
[aController mapCommandToVCO:@"logMessage" withFunction:@"LoggingVCO"];

Le contrleur dapplication reoit le message mapCommandToVCO:withFunction, dans


lequel le premier paramtre est la commande et le second, le nom du VCO. Cette mthode,
ainsi que dautres comme elle, utilise pour associer les types dobjets de commande, sont
des faades qui appellent la mthode mapCommandToCO sous-jacente.
La mthode mapCommandToCO permet dassocier plusieurs objets de commande une
seule commande en utilisant un NSMutableArray. Ce tableau contient les objets Class qui
correspondent aux noms de classe passs en second paramtre. Le code suivant prsente
limplmentation de la mthode mapCommandToCO.
- (void) mapCommandToCO:(NSString*)aCommand
withFunction:(NSString*)aClassName
toMap:(NSMutableDictionary*)aMap{
NSMutableArray *controlObjects =
[[aMap objectForKey:aCommand] retain];
if(controlObjects == nil){
NSMutableArray *tmpCntrlObjs =
[[NSMutableArray alloc] initWithCapacity:1];
[aMap setObject: tmpCntrlObjs forKey:aCommand];
controlObjects = tmpCntrlObjs;
[tmpCntrlObjs release];
}
// Obtenir la classe de lobjet de contrle
// pour le nom indiqu et ajouter un objet
// de ce type au tableau de la commande.
Class aClass = NSClassFromString(aClassName);
if(aClass!= nil){
[controlObjects addObject:aClass];
}
else{
MESSAGE(@"Erreur: classe %@ non trouve.
Vrifiez quelle existe sous ce nom et recommencez.");
}
}

Lajout des objets Class NSMutableArray permet dassocier nimporte quel nombre
dobjets de commande de mme type, VCO, BCO ou autres, la mme commande et de
les excuter ensuite individuellement dans lordre o les messages mapCommandTo* ont t
envoys. Ainsi, plusieurs VCO peuvent tre excuts squentiellement.

iPhone Livre Page 113 Vendredi, 30. octobre 2009 12:04 12

Chapitre 4

GPS, acclromtre et autres fonctions natives avec QuickConnectiPhone

113

Par exemple, un VCO peut afficher un UIView suivi dun autre qui modifie lopacit dun
autre UIView, pour terminer par la journalisation dun message. Pour cela, il suffit
denvoyer trois messages mapCommandToVCO avec la mme commande, mais avec trois
noms dobjets de commande diffrents.
Vous trouverez dautres exemples de BCO et de VCO dans lapplication DeviceCatalog.
Chacun est activ par des requtes effectues depuis la partie JavaScript de lapplication.

En rsum
Ce chapitre a montr comment activer plusieurs fonctionnalits trs demandes de
liPhone ou de liPod Touch depuis une application JavaScript. Lutilisation de la localisation GPS, des valeurs de lacclromtre, du vibreur du tlphone et du lecteur de sons ou
de fichiers audio permet denrichir votre application.
En tudiant le code de lapplication DeviceCatalog et en connaissant Objective-C, vous
devez tre en mesure dajouter dautres fonctionnalits, comme le scan du rseau Bonjour
la recherche des appareils du voisinage, lajout, la suppression et lobtention des contacts
partir de lapplication Contacts, ou lexploitation dautres comportements intgrs
disponibles aux applications Objective-C.
En se fondant sur lapproche dcrite dans ce chapitre, votre application JavaScript a les
moyens de raliser quasiment tout ce quune application Objective-C peut effectuer. Le
Chapitre 6 en prsentera un exemple, qui consistera embarquer des cartes Google dans
une application en conservant laspect de lapplication de cartographie dApple.

iPhone Livre Page 114 Vendredi, 30. octobre 2009 12:04 12

iPhone Livre Page 115 Vendredi, 30. octobre 2009 12:04 12

5
GPS, acclromtre et
autres fonctions natives
avec PhoneGap
La bibliothque PhoneGap constitue une alternative au framework QuickConnect, qui a
fait lobjet du Chapitre 4. Bien quelle noffre pas toutes les possibilits de QuickConnect,
elle est souvent utilise pour accder aux informations de lappareil et ses fonctions. La
premire section de ce chapitre explique comment accder aux fonctionnalits natives de
liPhone en utilisant lAPI JavaScript de PhoneGap. La seconde prsente le code JavaScript et Objective-C qui se cache derrire cette API.

Section 1 : activation de lappareil en JavaScript


Au moment de lcriture de ces lignes, le dveloppement de PhoneGap en est toujours
ses dbuts. Il gre donc un nombre limit de fonctionnalits natives. Cette section prsente
uniquement les comportements qui sont pris en charge du ct JavaScript et du ct

iPhone Livre Page 116 Vendredi, 30. octobre 2009 12:04 12

116

Dveloppez des applications pour liPhone

Objective-C de lapplication. Certaines parties du code de la bibliothque ne sont pas


encore termines ou pleinement oprationnelles. Les comportements correspondants ne
seront donc pas examins.
Le Tableau 5.1 recense les mthodes, les fonctions et les attributs qui font partie de lAPI
oprationnelle. Contrairement QuickConnectiPhone, elles ne se trouvent pas dans un
framework plus vaste et doivent donc tre invoques directement. Puisque les contrles
effectus par la version actuelle sont minimaux, vous devez vrifier que les paramtres
passs aux fonctions sont valides et non null.
Nous lavons expliqu au Chapitre 4, QuickConnectiPhone inclut les fichiers HTML, CSS
et JavaScript dans lapplication installe sur lappareil. Ce nest pas le cas de PhoneGap 1.
la place, une application Objective-C gnrique de dmarrage, laquelle est donn le
nom de votre application, charge temporairement ces fichiers partir dun serveur web sur
lequel vous les avez pralablement publis (voir Figure 5.1). Pour excuter votre application, lappareil doit donc tre connect au rseau. Par consquent, vous ne devez pas
supposer que votre application fonctionnera correctement si lutilisateur se trouve dans un
avion o le rseau est inaccessible.
Dmarrage dune application PhoneGap

Requte

URL
de requte

URL
de requte
Serveur web

Rponse

HTML,
CSS
et JavaScript

HTML,
CSS
et JavaScript

Serveur web

Figure 5.1
Avec PhoneGap, lobtention des fichiers HTML, CSS et JavaScript dune application se fait
par un change requte-rponse.
1. N.d.T. : rappelons qu partir de la version 0.7.3 PhoneGap enregistre les fichiers JavaScript, HTML
et CSS sur lappareil, non plus sur un serveur web.

iPhone Livre Page 117 Vendredi, 30. octobre 2009 12:04 12

Chapitre 5

GPS, acclromtre et autres fonctions natives avec PhoneGap

117

Lorsquune application PhoneGap dbute le chargement de ses composants web partir


du serveur, un appel est effectu depuis lapplication Objective-C gnrique vers le code
JavaScript. Cet appel fixe les valeurs de plusieurs variables globales qui dcrivent lappareil sur lequel lapplication sexcute. La mthode Device.init de lAPI JavaScript,
gnralement appele depuis une fonction dfinie comme gestionnaire des vnements
onload, collecte les variables globales dfinies par la partie Objective-C de lapplication et
les enregistre dans des attributs de lobjet Device de PhoneGap. Le code Objective-C qui
dfinit ces variables sera prsent la Section 2.
init: function(model, version) {
...
Device.available = __gap;
Device.model = __gap_device_model;
Device.version = __gap_device_version;
Device.gapVersion = __gap_version;
Device.uuid = __gap_device_uniqueid;
...
}

Le code prcdent concerne les iPhone et iPod Touch. Chaque nom de variable globale
dbute par __ (deux souligns) et a une valeur unique. La variable __gap est utilise
comme indicateur qui prcise si le code JavaScript sexcute depuis une application
PhoneGap. Au moment de lcriture de ces lignes, cette variable est indispensable car les
fichiers HTML, CSS et JavaScript sont non pas inclus dans une application compile et
installe, mais tlchargs via Internet par lenveloppe PhoneGap. Si ces fichiers de
lapplication sont chargs depuis un navigateur web la place dune application
PhoneGap, la variable __gap vaut null et peut tre utilise pour excuter du code
conditionnel.
La variable __gap_device_model contient une chane de caractres qui dcrit lappareil
sur lequel sexcute lapplication, comme iPhone, iPod Touch ou iPhone Simulator. Elle
inclut galement la version du systme dexploitation de lappareil, qui est enregistre
dans la variable globale __gap_device_version. Lidentifiant global unique de lappareil
se trouve dans la variable __gap_device_uniqueid, tandis que la version de PhoneGap
est place dans __gap_version. Chacune de ces variables est disponible dans les attributs
publics de Device ou dans les variables globales. Le Tableau 5.1 dcrit chaque fonction
JavaScript qui vous permet daccder aux fonctionnalits de lappareil.
Lexemple PGDeviceCatalog comprend un bouton Vibrate qui, lorsque lutilisateur
clique dessus, fait vibrer le tlphone.

iPhone Livre Page 118 Vendredi, 30. octobre 2009 12:04 12

118

Dveloppez des applications pour liPhone

Tableau 5.1 : API JavaScript de PhoneGap

lment

Paramtres

gotAcceleration() x la valeur de lacclration


selon laxe X.

y la valeur de lacclration
selon laxe Y.

Comportement
Cette fonction nest pas prdfinie. Pour obtenir
les informations de lacclromtre, vous devez
crer cette fonction quelque part dans votre application. Le code Objective-C peut ensuite linvoquer en lui passant les valeurs en paramtres.

z la valeur de lacclration
selon laxe Z.
Device.init()

Aucun.

Collecte les informations concernant lappareil


partir des variables globales dfinies au dmarrage de lapplication. Ces informations sont places dans lobjet Device et incluent le type de
lappareil (iPhone/iPodTouch), la version de son
systme dexploitation, son identifiant unique,
ainsi que la version de PhoneGap.

Device.vibrate()

Aucun.

Dclenche le vibreur du tlphone pendant la


dure standard.

Device.sound()

clip une chane de caractres Le fichier audio de nom indiqu doit se trouver
qui prcise le nom et le type du dans les ressources de lapplication ou une erreur
fichier audio jouer, par exemple dexcution sera gnre.
"tweet.wav".

Device.Location.init()

Aucun.

Si une fonction de rappel est affecte cet attribut


de lobjet Location, elle est invoque lorsque les
informations GPS sont disponibles.

Device.Location.callback
Device.Location.wait()

Dclenche lenvoi des informations de localisation dj prsentes dans la partie Objective-C au


code JavaScript en vue de leur traitement et/ou de
leur affichage.

func la fonction de rappel ex- Il sagit dune alternative la fonction


cute lorsque les informations
Device.Location.init().
GPS sont disponibles.

Device.exec()

command une chane de commande passe la partie Objective-C de lapplication en vue de


son traitement, par exemple
"vibrate", "sound" ou "getLoc".

Cette fonction prend en charge toutes les communications avec la partie Objective-C de lapplication. Chaque commande envoye dclenche un
comportement natif diffrent de lappareil. Cette
mthode doit tre invoque depuis JavaScript si
vous crez un code Objective-C personnalis que
vous souhaitez excuter.

iPhone Livre Page 119 Vendredi, 30. octobre 2009 12:04 12

Chapitre 5

GPS, acclromtre et autres fonctions natives avec PhoneGap

119

Le gestionnaire dvnements onclick du bouton est la fonction nomme vibrateDevice. Elle appelle la mthode Device.vibrate qui dclenche le vibreur.
function vibrateDevice(event)
{
Device.vibrate();
}

La mthode Device.vibrate suivante est une faade pour la mthode exec de lobjet
Device. Elle invoque Device.exec en lui passant la commande vibrate. Toutes les
mthodes PhoneGap associes aux fonctionnalits de lappareil sont en ralit des faades
pour Device.exec.
vibrate: function() {
return Device.exec("vibrate")
}

La fonction Device.exec utilise dans le code prcdent est crite en JavaScript (voir ciaprs). linstar de QuickConnectiPhone, PhoneGap construit lURL et cre un message
compos de lURL et de la commande, comme vibrate, qui est envoy un composant
Objective-C faisant partie du framework PhoneGap sous-jacent. Ce composant arrte le
chargement de la nouvelle page et value les commandes envoyes. Pour de plus amples
informations concernant cette procdure, consultez la Section 2.
exec: function(command) {
if (Device.available) {
try {
document.location = "gap:" + command;
} catch(e) {
console.log("La commande " + command +
" na pas t excut en raison de lexception: " + e);
alert("Erreur dexcution de la commande " + command + ".")
}
}
}

Dans la partie catch du code prcdent, deux mcanismes sont utiliss pour indiquer un
problme lutilisateur. Le premier, un appel console.log, crit un message sur la
console de Dashcode. Il fonctionne uniquement lorsque lapplication sexcute dans Dashcode, non sur lappareil.
Le second mcanisme se fonde sur une bote dalerte. Puisque PhoneGap a mis en uvre
les botes dalerte en Objective-C, cette solution fonctionne sur lappareil, mais, selon les
directives dApple, elle ne devrait jamais tre utilise dans les applications pour liPhone.

iPhone Livre Page 120 Vendredi, 30. octobre 2009 12:04 12

120

Dveloppez des applications pour liPhone

Pour de plus amples informations sur la conception de linterface utilisateur des applications
pour liPhone, consultez le Chapitre 3.
Les mthodes playSound et vibrate sont toutes deux unidirectionnelles, avec une
communication depuis JavaScript vers Objective-C, sans donnes retournes. La mthode
Device.Location.init est bidirectionnelle et des donnes fournies par la partie Objective-C de PhoneGap sont donc attendues. Comme le montre lexemple suivant, cette
mthode init est galement une faade pour la mthode Device.exec. Dans son cas, la
commande passe se nomme getloc.
init: function() {
...
Device.exec("getloc");
...
}

La Figure 5.2 illustre lexcution dune application PhoneGap qui a demand des informations de localisation GPS. Cette requte se fait galement au travers dune faade qui invoque
Device.exec.
Figure 5.2
Lapplication PGDeviceCatalog affiche des informations concernant la
localisation GPS et
lappareil.

Dans lapplication PGDeviceCatalog, la mthode Device.Location.init est appele


partir de la fonction getGPS constitue de quatre lignes. La troisime ligne invoque init
et signale la partie Objective-C que ses donnes GPS enregistres sont requises.

iPhone Livre Page 121 Vendredi, 30. octobre 2009 12:04 12

Chapitre 5

GPS, acclromtre et autres fonctions natives avec PhoneGap

121

function getGPS(event){
Device.Location.callback = updateLocation;
Device.Location.init();
}

La deuxime ligne de getGPS informe lobjet Device.Location que la fonction updateLocation, dfinie dans main.js, doit tre appele lorsque les donnes GPS ont t obtenues. Dans PhoneGap, ce processus est beaucoup plus rapide que dans
QuickConnectiPhone, car la bibliothque Objective-C de PhoneGap active le matriel
GPS de lappareil ds que lapplication est dmarre et le dsactive lorsquelle est quitte.
Lactivation du matriel GPS pendant tout le temps dexcution des applications PhoneGap, mme si les donnes ne sont pas employes, utilise une quantit importante dnergie
de la batterie. Cette consommation est tellement importante quApple prcise que laisser
le matriel GPS activ pendant la dure dexcution dune application revient tre "un
mauvais voisin". Avec cette approche, la batterie de lappareil risque de ne plus avoir suffisamment de puissance pour les appels tlphoniques et lexcution dautres applications.
Cest pourquoi les applications PhoneGap doivent tre conues de manire sexcuter
pendant de courtes priodes de temps, mme si elles nexploitent pas les informations
GPS. Puisque QuickConnectiPhone dmarre le matriel GPS lorsque les informations de
localisation sont demandes et larrte ds quelles ont t obtenues, les applications dveloppes avec ce framework peuvent tre conues pour des dures dutilisation beaucoup
plus longues.
Pour obtenir les donnes de lacclromtre, une fonction nomme gotAcceleration(x, y,
z) doit tre implmente quelque part dans lapplication. Dans lexemple de PGDeviceCatalog, elle se trouve dans le fichier main.js.
function gotAcceleration(x, y, z){
document.getElementById(accelDisplay).innerHTML =
X: +x+<br/>Y: +y+ <br/>Z: +z;
}

Cette version de la fonction gotAcceleration affiche uniquement les valeurs de lacclromtre. Dans votre implmentation, vous pouvez les utiliser de diffrentes manires, par
exemple comme un filtre passe-bas ou pour modifier linterface utilisateur.
Puisque le simulateur de liPhone ne donne pas accs lacclromtre, vous devez excuter
lapplication sur un appareil rel pour voir laffichage de ces informations. Dans ce cas, la
fonction gotAcceleration est appele chaque fois que lacclromtre dtecte un
mouvement.
La bibliothque PhoneGap permet galement de jouer un fichier audio depuis du code
JavaScript. La fonction playTweetSound constitue un exemple de cette fonctionnalit.

iPhone Livre Page 122 Vendredi, 30. octobre 2009 12:04 12

122

Dveloppez des applications pour liPhone

Elle appelle la mthode Device.playSound, qui, linstar de la mthode


Device.vibrate, est une faade pour Device.exec.
function playTweetSound(event) {
Device.playSound(bird.mp3);
}

La mthode playSound requiert en argument le nom complet du fichier audio jouer. Ce


fichier doit se trouver dans le groupe Resources du projet Xcode de lapplication. Il ne
peut pas tre plac sur le serveur web avec les fichiers HTML, JavaScript et CSS. Sil nest
pas inclus aux ressources de lapplication, il nest pas lu.
Dans notre exemple, bird.mp3 est pass la mthode playSound de lobjet Device et il est
utilis en paramtre de la commande sound (voir ci-aprs). ce stade du dveloppement
de PhoneGap, playSound est la seule mthode oprationnelle qui gre une commande
avec des paramtres. Il semble que cela changera lorsque lquipe de dveloppements de
PhoneGap ajoutera dautres fonctionnalits. Pour de plus amples informations concernant
la feuille de route de PhoneGap, consultez lAnnexe C.
playSound: function(clip) {
return Device.exec(sound: + clip);
}

Cette section a montr comment activer les fonctionnalits natives de lappareil au travers
de PhoneGap. La Section 2 dcrit la partie Objective-C de la bibliothque PhoneGap qui
prend en charge cette possibilit.

Section 2 : activation de lappareil en Objective-C


Si vous ntes pas familier du langage Objective-C et de son utilisation dans le dveloppement dapplications pour liPhone, consultez le livre dErica Sadun, The iPhone Developers Cookbook. Si vous souhaitez simplement utiliser la bibliothque PhoneGap pour
crire des applications JavaScript pour liPhone, vous ntes pas oblig de lire cette
section.
Aprs que les fichiers HTML, CSS et JavaScript de lapplication ont t obtenus partir
du serveur web, lAPI dclenche un vnement intercept et trait par la mthode
webViewDidStartLoad de lobjet GlassAppDelegate. Son rle est dinitialiser un objet
PhoneGap Device.
// Au chargement de lapplication web, lui passer
// les informations concernant lappareil.

iPhone Livre Page 123 Vendredi, 30. octobre 2009 12:04 12

Chapitre 5

GPS, acclromtre et autres fonctions natives avec PhoneGap

123

- (void)webViewDidStartLoad:(UIWebView *)theWebView {
[theWebView stringByEvaluatingJavaScriptFromString:
[[Device alloc] init]];
}

La mthode init de lobjet Device cre une chane de caractres constitue dune suite
dappels JavaScript. Chacun de ces appels fixe la valeur dune variable globale, notamment le modle de lappareil, iPhone ou iPod Touch, son identifiant unique et la version de
son systme dexploitation.
La chane cre est retourne par la mthode init afin quelle puisse tre utilise par la
mthode stringByEvaluatingJavaScriptFromString de lobjet UIWebView. Lvaluation de la chane par UIWebView permet de fixer les valeurs de variables JavaScript globales, comme __gap_device_uniqueid. Nous verrons plus loin dans ce chapitre comment
ces variables globales sont assembles dans un objet JavaScript.
@implementation Device
- (NSString *)init{
jsCallBack = nil;
myCurrentDevice = [UIDevice currentDevice];
return jsCallBack = [[NSString alloc] initWithFormat:@"\
__gap = true; \
__gap_version=0.1; \
__gap_device_model=%s; \
__gap_device_version=%s;\
__gap_device_uniqueid=%s;",
[[myCurrentDevice model] UTF8String],
[[myCurrentDevice systemVersion] UTF8String],
[[myCurrentDevice uniqueIdentifier] UTF8String]
];
}
- (void)dealloc {
[jsCallBack release];
[myCurrentDevice release];
[super dealloc];
}
@end

Ces variables globales sont fixes sans effectuer une requte. Dautres fonctionnalits
vous obligent crire du code qui dclenche le comportement souhait.

iPhone Livre Page 124 Vendredi, 30. octobre 2009 12:04 12

124

Dveloppez des applications pour liPhone

Lun des comportements les plus faciles implmenter en Objective-C est lactivation du
vibreur de liPhone. Il suffit en effet dune seule ligne de code lorsque le framework
AudioToolbox est inclus aux ressources du projet :
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);

Comment faire en sorte que la fonction AudioServicesPlaySystemSound soit appele


lorsque le code change lattribut location de UIWebView ?
La classe GlassAppDelegate implmente la mthode webView:shouldStartLoadWithRequest:navigationType. Puisque GlassAppDelegate est le dlgu du UIWebView embarqu (voir ligne 36 du fichier GlassAppDelegate.m), nomm aWebView, cette
mthode est invoque chaque fois que le UIWebView embarqu voit son attribut location
modifi.
webView.delegate = self;

Le comportement de base de la fonction webView:shouldStartLoadWithRequest:navigationType est simple. Sa conception vous permet dcrire du code qui dcide si la
nouvelle page demande doit tre rellement charge. La bibliothque PhoneGap se fonde
sur cette possibilit de dcision pour interdire les requtes de commande effectues par les
appels JavaScript dcrits la Section 1 et pour excuter un autre code Objective-C.
La mthode shouldStartLoadWithRequest prend plusieurs paramtres :

curWebView. Le UIWebView qui contient lapplication JavaScript.

request. Un NSURLRequest qui contient, entre autres, la nouvelle URL.

navigationType. Un UIWebViewNavigationType qui peut tre utilis pour dterminer si la requte est le rsultat dun clic sur un lien ou si elle a t gnre suite une
autre action.
-(BOOL)webView:(UIWebView *)curWebView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType

LURL compose par la mthode JavaScript Device.exec pour faire vibrer le tlphone,
gap:vibrate, est contenue dans lobjet request et peut tre facilement retrouve sous
forme dune chane de caractres en envoyant le message URL cet objet. Ce message
retourne un objet de type NSURL, auquel est ensuite pass le message absoluteString.
Nous obtenons ainsi un pointeur NSString qui reprsente lURL.
NSString *url = [[request URL] absoluteString];
NSArray *urlArray = [url componentsSeparatedByString:@"?"];

iPhone Livre Page 125 Vendredi, 30. octobre 2009 12:04 12

Chapitre 5

GPS, acclromtre et autres fonctions natives avec PhoneGap

125

Dans PhoneGap, on dtermine si lURL demande est relative celle de lapplication indique dans le fichier url.txt. Dans la ngative, le navigateur Safari est lanc pour afficher la
page dsigne par lURL. Dans ce cas, lapplication se termine, car liPhone nautorise
lexcution que dune seule application la fois.
Le code suivant obtient lhte demand, indiqu dans le paramtre url, et lhte de
lapplication indiqu dans appURL. Pour cela, le message host est envoy aux deux objets
NSURL.
Les lignes 3 et 4 envoient le message rangeOfString la variable urlHost. Cela quivaut lappel de la mthode indexOf sur un objet JavaScript String. Le code suivant
dtermine si la valeur de lhte de lapplication est prsent dans lURL de requte.
1
2
3
4
5
6
7
8
9
10

NSString* urlHost = [url host];


NSString* appHost = [appURL host];
NSRange range = [urlHost rangeOfString:appHost
options:NSCaseInsensitiveSearch];
if (range.location == NSNotFound)
[[UIApplication sharedApplication] openURL:url];
NSString * jsCallBack = nil;
NSArray * parts = [urlString
componentsSeparatedByString:@":"];

La ligne 5 examine le rsultat de la mthode rangeOfString pour dterminer si appHost


a t trouv dans urlHost. Dans la ngative, le message openURL est envoy votre application. Chaque fois que ce message openURL est envoy, votre application se termine et
lapplication approprie est dmarre. Si une URL commenant par map: est demande,
lapplication de cartographie de liPhone est lance avec lURL indique. Les autres types
possibles sont notamment http, qui lance Safari, tel, qui lance loutil de numrotation
tlphonique, mailto, qui lance lapplication de messagerie, et les URL youtube.com,
qui lancent lapplication YouTube. Dans tous les cas, votre application se termine.
Les lignes 9 et 10 dcomposent lURL de manire obtenir les composantes de la
commande et placent chacune delles dans un tableau nomm parts. Celui-ci est ensuite
valu pour dterminer la commande envoye et ses paramtres.
PhoneGap utilise une instruction conditionnelle if-then-else pour valuer le tableau
parts. Chaque commande active une condition diffrente. Dans la condition de la
commande vibrate, un objet Vibrate est instanci et le message vibrate lui est pass.
else if([(NSString *)[parts objectAtIndex:1]
isEqualToString:@"vibrate"]){
Vibrate *vibration = [[Vibrate alloc] init];
[vibration vibrate];

iPhone Livre Page 126 Vendredi, 30. octobre 2009 12:04 12

126

Dveloppez des applications pour liPhone

[vibration release];
NSLog(@"vibreur dclench");
}

Cest dans la mthode vibrate de lobjet Vibrate (fichier Vibrate.m) que lappel AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); est effectu.
Le traitement des requtes concernant les informations GPS est diffrent. Cette commande
est gre directement au lieu dtre passe un objet qui la prendra en charge. Les lignes 5
7 crent une chane qui contient un appel JavaScript la fonction gotLocation(lat,
lon) dfinie dans le fichier phonegap.js, o lat et lon sont remplacs par la latitude et la
longitude courantes ; ces informations sont dtermines en permanence depuis le dmarrage de lapplication.
1 if([(NSString *)[parts objectAtIndex:1]
2
isEqualToString:@"getloc"]){
3
NSLog(@"location request!");
4
5
jsCallBack = [[NSString alloc]
6
initWithFormat:@"gotLocation(%f,%f);"
7
, lat, lon];
8
NSLog(@"callback: %@",jsCallBack);
9
[theWebView
10
stringByEvaluatingJavaScriptFromString:
11
jsCallBack];
12
13
[jsCallBack release];
14 }

Pour dclencher lexcution de la chane JavaScript jsCallBack, le message stringByEvaluatingJavaScriptFromString, accompagn de la chane JavaScript en paramtre,
doit tre envoy lobjet UIWebView pass dans le paramtre theWebView la fonction
shouldStartLoadWithRequest. ce stade, la partie Objective-C de la bibliothque a
termin son travail.
La fonction JavaScript gotLocation appelle prsent la mthode set de lobjet
Device.Location :
function gotLocation(lat, lon) {
return Device.Location.set(lat, lon)
}

La mthode Device.Location.set enregistre la latitude et la longitude dans lobjet


Device.Location et appelle ensuite la fonction de rappel callback, si elle existe, comme
nous lavons expliqu la Section 1. Notez quaprs linvocation de la fonction de rappel

iPhone Livre Page 127 Vendredi, 30. octobre 2009 12:04 12

Chapitre 5

GPS, acclromtre et autres fonctions natives avec PhoneGap

127

la ligne 6 fixe lattribut callback null. Autrement dit, chaque fois que vous demandez
des informations de localisation, vous devez reprciser la mthode de rappel.
1
2
3
4
5
6
7
8

set: function(lat, lon) {


Device.Location.lat = lat;
Device.Location.lon = lon;
if(Device.Location.callback!= null) {
Device.Location.callback(lat, lon)
Device.Location.callback = null;
}
}

Si vous ne dfinissez pas une mthode callback chaque fois que vous demandez des
informations de localisation, aucune fonction de rappel nest invoque.
Le traitement de la commande sound est comparable celui de la commande getloc.
Toutefois, puisque la partie JavaScript de lapplication nattend aucune donne, le
message stringByEvaluatingJavaScriptFromString nest pas envoy UIWebView.
la place, un objet Sound est cr comme dans le cas de la commande vibrate.
1 else if ([(NSString *)[parts objectAtIndex:1]
2
isEqualToString:@"sound"]) {
3
NSLog(@"playing sound");
4
NSLog([parts objectAtIndex:2]);
5
NSString *ef = (NSString *)[parts objectAtIndex:2];
6
NSArray *soundFile = [ef componentsSeparatedByString:@"."];
7
8
NSString *file = (NSString *)[soundFile objectAtIndex:0];
9
NSString *ext = (NSString *)[soundFile objectAtIndex:1];
10
NSLog(@"about to allocate %@, %@",file, ext);
11
sound = [[Sound alloc] initWithContentsOfFile:
12
[mainBundle pathForResource:file ofType:ext]];
13
NSLog(@"sound allocated");
14
[sound play];
15 }

Cet objet Sound, dfini dans Sound.m, est initialis avec le chemin du fichier audio. Nous
lavons indiqu la Section 1, ce fichier doit rsider dans le groupe Resources du projet
Xcode. Par consquent, nous pouvons envoyer lobjet mainBundle, qui reprsente
lapplication installe, le message pathForResource:ofType afin dobtenir le chemin
complet du fichier audio sur lappareil (lignes 11 et 12). La ligne 14 envoie le message
play lobjet Sound pour que le fichier soit jou.
La mthode initWithContentsOfFile de lobjet Sound montre comment convertir des
fichiers audio, par exemple des fichiers mp3, en sons systme. Pour cela, les fichiers audio

iPhone Livre Page 128 Vendredi, 30. octobre 2009 12:04 12

128

Dveloppez des applications pour liPhone

doivent tre trs courts. En ralit, Apple suggre quils durent moins de 5 secondes.
Chaque son systme est cr partir de lURL de son emplacement. La ligne 1 du code
suivant illustre cette procdure avec une chane de chemin quelconque. La ligne 3 cre
lURL.
1
2
3
4
5

- (id) initWithContentsOfFile:(NSString *)path


{
...
NSURL *filePath = [NSURL fileURLWithPath:path isDirectory:NO];
AudioServicesCreateSystemSoundID((CFURLRef)filePath, &soundID);
...
}

La ligne 4 convertit le fichier audio en son systme. Les sons systme diffrent des fichiers
audio standard car ils sont interprts et enregistrs dans le systme dexploitation luimme. Pour les jouer, aucun lecteur multimdia nest ncessaire. Linvocation de la fonction
AudioServicesCreateSystemSoundID suffit.
Cette fonction prend deux arguments. Le premier correspond lURL du fichier audio, le
second est un pointeur sur un SystemSoundID. Dans lexemple, ce SystemSoundID est
lattribut soundID de lobjet Sound, qui est utilis ensuite pour jouer le son dans la
mthode play de lobjet Sound.
Comme le montre le code suivant, cette mthode play occupe une seule ligne de code. Un
appel la fonction AudioServicesPlaySystemSound, en lui passant un SystemSoundID,
suffit pour que lutilisateur entende le son.
- (void) play {
AudioServicesPlaySystemSound(soundID);
}

Quel que soit le fichier audio choisi comme son systme, voici les tapes de sa cration et
de son utilisation :
1. Obtenir une URL qui dsigne lemplacement du fichier audio sur lappareil.
2. Gnrer le son systme et enregistrer son identifiant.
3. Jouer le son systme.
Avec PhoneGap, le son systme est gnr chaque fois que vous demandez sa lecture, ce
qui nest pas trs efficace. Il est prfrable de crer le son une seule fois et de le jouer
ensuite autant de fois que vous voulez.
Nous lavons mentionn prcdemment, PhoneGap active le matriel GPS au dmarrage de lapplication. Cela se passe dans les trois premires lignes de la mthode

iPhone Livre Page 129 Vendredi, 30. octobre 2009 12:04 12

Chapitre 5

GPS, acclromtre et autres fonctions natives avec PhoneGap

129

applicationDidFinishLaunching de la classe GlassAppDelegate. Le code suivant


montre que ces trois lignes initialisent un CLLocationManager, lenregistre dans lattribut
locationManager de la classe GlassAppDelegate et lui demande de commencer lactualisation des informations GPS.
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager startUpdatingLocation];

La classe CLLocationManager sert denveloppe au matriel GPS et Wi-Fi qui dtermine la


localisation courante de lappareil. Elle se fonde sur la puce GPS et les points daccs Wi-Fi
ouverts pour dterminer la latitude et la longitude actuelles.
La deuxime ligne du code prcdent demande lobjet locationManager dappeler la
mthode didUpdateToLocation de GlassAppDelegate chaque fois quun changement
de localisation est dtect. Pour cela, elle fixe le dlgu de lobjet locationManager au
GlassAppDelegate courant reprsent par le mot cl self. Pour de plus amples informations concernant les dlgus, consultez les Chapitres 2 et 4 du livre The iPhone Developers
Cookbook: Building Applications with the iPhone SDK, dErica Sadun.
La mthode dlgue appele chaque changement de localisation se nomme didUpdateToLocation ; elle est dfinie dans le fichier GlassAppDelegate.m. Comme le montre le
code suivant, elle efface toute localisation dj enregistre, pour la remplacer par la localisation actuelle passe la mthode dans le paramtre newLocation. Nous lavons vu
prcdemment, cette information est utilise par shouldStartLoadWithRequest dans sa
condition getloc.
-(void)locationManager:(CLLocationManager *)manager
// Note de lauteur.
// Il y a un bogue potentiel ici.
// Si newLocation == lastKnown alors
// lobjet newLocation est libr
// [newLocation retain] doit tre appel
// avant [lastKnownLoation release]
// Le code prsent est celui fourni
// par PhoneGap.
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
[lastKnownLocation release];
lastKnownLocation = newLocation;
[lastKnownLocation retain];
}

iPhone Livre Page 130 Vendredi, 30. octobre 2009 12:04 12

130

Dveloppez des applications pour liPhone

Lactivation de lacclromtre est gre de manire semblable celle du GPS. Les trois
lignes de code suivantes demandent lacclromtre denregistrer ses donnes quarante
fois par seconde et fixent ensuite le dlgu lobjet GlassAppDelegate courant, comme
pour le gestionnaire de localisation.
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:1.0/40.0];
[[UIAccelerometer sharedAccelerometer] setDelegate:self];

Dans ce cas, la mthode appele est non pas didUpdateToLocation mais didAccelerate.
Le code suivant montre que la mthode didAccelerate ressemble normment la
mthode didUpdateToLocation. Elle obtient les informations de lacclromtre, mais,
au lieu de les enregistrer localement ct Objective-C de la bibliothque, elle les envoie
la partie JavaScript de manire comparable au traitement de la commande gotloc vue
prcdemment.
-(void) accelerometer:(UIAccelerometer *)accelerometer
didAccelerate:(UIAcceleration *)acceleration {
NSString * jsCallBack = nil;
NSLog(@"accelerating");
jsCallBack = [[NSString alloc]
initWithFormat:
@"gotAcceleration(%f,%f,%f);",
acceleration.x,
acceleration.y,
acceleration.z];
[webView stringByEvaluatingJavaScriptFromString:jsCallBack];
}

Si la mthode shouldStartLoadWithRequest reconnat dautres commandes, aucune


delles nest oprationnelle au moment de lcriture de ces lignes, et elles nont donc pas
t prsentes. Toutes les commandes dcrites dans cette section fonctionnent et sont
disponibles dans le programme dinstallation du modle Xcode pour les applications
PhoneGap.

En rsum
Ce chapitre a montr comment activer plusieurs fonctionnalits trs demandes de
liPhone ou de liPod Touch depuis une application JavaScript en utilisant la bibliothque
PhoneGap. Grce aux fonctionnalits natives de ces appareils, comme la localisation GPS,
lacclromtre, le vibreur et les sons, vous pouvez enrichir vos applications.

iPhone Livre Page 131 Vendredi, 30. octobre 2009 12:04 12

Chapitre 5

GPS, acclromtre et autres fonctions natives avec PhoneGap

131

En tudiant les exemples inclus avec PGDeviceCatalog et en connaissant Objective-C,


vous devez tre en mesure dajouter des fonctionnalits supplmentaires, comme le scan
du rseau Bonjour la recherche des appareils du voisinage, lajout, la suppression et
lobtention des contacts partir de lapplication Contacts, ou lexploitation dautres
comportements natifs disponibles aux applications Objective-C.
En se fondant sur lapproche dcrite dans ce chapitre, votre application JavaScript dispose
pratiquement des mmes possibilits quune application Objective-C.

iPhone Livre Page 132 Vendredi, 30. octobre 2009 12:04 12

iPhone Livre Page 133 Vendredi, 30. octobre 2009 12:04 12

6
Cartes Google
De nombreuses applications pour liPhone utilisent des cartes gographiques. Pour afficher ces cartes, il existe diffrentes mthodes, comme fermer lapplication en cours et
ouvrir lapplication de cartographie fournie par Apple, ou utiliser une carte Google. Ces
deux approches prsentent certaines limites. Ce chapitre explique comment crer une carte
Google et lutiliser la manire de lapplication de cartographie de liPhone sans fermer
lapplication en cours.

Section 1 : afficher une carte dans une application


JavaScript QuickConnect
Dans les applications hybrides pour liPhone, les programmeurs peuvent utiliser des cartes
de diffrentes manires. La solution la plus simple consiste ajouter un lien qui dbute par
http://maps.google.com et contient les informations gographiques souhaites. Lorsque
lutilisateur ouvre un tel lien, lapplication en cours se termine et lapplication de cartographie
standard est dmarre pour afficher la carte demande.
Cette approche simple est facile et rapide mettre en uvre. Toutefois, lapplication en
cours est termine, ce qui constitue gnralement une mauvaise conception logicielle.

iPhone Livre Page 134 Vendredi, 30. octobre 2009 12:04 12

134

Dveloppez des applications pour liPhone

Lapplication donne un sentiment dinachev, et les utilisateurs ont en ralit besoin dune
approche plus intgre.
Par ailleurs, mme si Google peut rpondre des requtes, comme "pizza", et placer de
nombreuses punaises, il est actuellement impossible de mettre plusieurs punaises sur des
emplacements que vous dfinissez. Par exemple, vous pourriez souhaiter placer des punaises en diffrents lieux dune ville. Si ces lieux ne correspondent pas des points dintrt
que lon peut rechercher, comme "pizza", vous ne pourrez pas placer les punaises en ajoutant une description de chaque lieu lURL soumise Google. Cette limitation est gnante
lorsque lon veut dfinir les lieux punaiss par leur latitude et longitude.
Une autre solution consiste mettre en uvre dans lapplication un comportement
semblable celui obtenu avec une page web standard. LAPI AJAX de Google est alors
utilise pour embarquer une carte dans un <div> du contenu HTML affich. Ensuite,
chaque punaise est place indpendamment en passant par lAPI JavaScript de Google.
Si cette approche permet de garder lutilisateur dans lapplication, elle prsente galement
des inconvnients. Tout dabord, le UIWebView qui affiche la carte nautorise pas le dfilement dans les <div>. Les vnements de toucher et de dplacement sont traits un
niveau infrieur et ne sont pas transmis la partie JavaScript de Google qui interagit avec
la carte embarque. Autrement dit, vous pouvez afficher la carte, mais il est impossible de
la dplacer pour changer la zone affiche.
Par ailleurs, la taille des bulles dinformation sur les lieux proposes en standard par
Google pose problme. Elles sont dimensionnes pour un affichage dans un navigateur sur
un ordinateur. Lorsquelles sont affiches sur liPhone, elles ont tendance recouvrir une
grande partie de la carte. La plupart des bulles apparaissent gnralement hors de lcran
et, en raison du problme de dfilement mentionn prcdemment, ne sont pas visibles.
Sil est possible de limiter la longueur du contenu de ces bulles, il est impossible den
changer la taille.
La solution idale serait dembarquer la carte dans lapplication et de proposer laffichage de plusieurs punaises, comme dans la seconde option, tout en gardant les possibilits de dfilement et daffichage de la premire. Le framework QuickConnectiPhone
propose un composant qui permet de mettre en uvre cette solution par un seul appel
de JavaScript.
Le projet Xcode MapExample montre comment procder. Lcran principal de cet exemple comprend un seul bouton HTML (voir Figure 6.1). Le gestionnaire onclick de ce
bouton est la fonction showTheMap dfinie dans le fichier main.js et dont le code est donn
ci-aprs. Elle configure quatre lieux : la ville de Rexburg dans lIdaho, le Wyoming, une
contre plus sauvage et une sandwicherie.

iPhone Livre Page 135 Vendredi, 30. octobre 2009 12:04 12

Chapitre 6

Cartes Google

Figure 6.1
Lcran principal
de lapplication
MapExample comprend
un bouton HTML.

function showTheMap(event)
{
// Un lieu est dfini par une latitude,
// une longitude et une description.
var locationsArray = new Array();
rexburg = new Array();
rexburg.push(43.82211);
rexburg.push(-111.76860);
rexburg.push("Mairie");
locationsArray.push(rexburg);
var wyoming = new Array();
wyoming.push(42.86);
wyoming.push(-109.45);
wyoming.push("Place de Wyoming");
locationsArray.push(wyoming);
var wilderness = new Array();
wilderness.push(45.35);
wilderness.push(-115);
wilderness.push("Rivire du sans retour ");
locationsArray.push(wilderness);
var sandwichShop = new Array();
sandwichShop.push(42.86);

135

iPhone Livre Page 136 Vendredi, 30. octobre 2009 12:04 12

136

Dveloppez des applications pour liPhone

sandwichShop.push(-112.45);
sandwichShop.push("Sandwicherie");
locationsArray.push(sandwichShop);
showMap(event, locationsArray);
}

Chaque lieu dfini est un tableau compos de trois lments : une latitude, une longitude et
une courte description afficher sur chaque punaise place. Ces lieux sont ajouts locationsArray. Si lordre des informations dfinissant chaque lieu est fig, le tableau locationsArray nimpose aucun ordre.
Dans une application relle, les informations concernant chaque lieu pourraient provenir
dune base de donnes, dun flux RSS ou dune autre source. Vous pouvez mme les obtenir dynamiquement pendant lexcution de lapplication. Si vous connaissez des adresses,
utilisez lAPI JavaScript de gocodage de Google pour obtenir la latitude et la longitude
correspondantes (http://code.google.com/apis/maps/documentation/services.html#Geo
coding_Object). Toutefois, ces requtes prennent du temps. Il est prfrable de commencer par obtenir les coordonnes des lieux intressants en lanant une tche lors de la
conception et denregistrer les rsultats avant de livrer lapplication.
Une fois que le tableau JavaScript contenant tous les lieux souhaits est cr, il est pass
la fonction showMap du framework, accompagn de lvnement qui a dclench lappel
la fonction showTheMap. ce stade, le framework prend le relais et, laide de la fonction
makeCall dcrite au Chapitre 4, demande la partie Objective-C dafficher une carte avec
des punaises sur chaque lieu (voir Figure 6.2).
Le framework affiche la carte dans un objet Objective-C MapView. La classe MapView,
dcrite la Section 2, permet lutilisateur demployer le toucher et le balayement pour
contrler la carte la faon de lapplication de cartographie dApple. Par un doubletoucher sur un lieu de la carte, lapplication centre laffichage sur ce lieu et ralise un
zoom avant. Lutilisateur peut galement faire un double-toucher sur une punaise pour
centrer la carte et effectuer un zoom sur le lieu correspondant.
Lorsque lutilisateur touche simplement une punaise, une courte description est affiche
dans une petite bote noire (voir Figure 6.3). Sil touche et fait glisser une punaise, il la
repositionne sur un nouveau lieu de la carte.
Lorsque lutilisateur na plus besoin de la carte, il slectionne le bouton Done pour faire
disparatre le MapView. Laffichage de lapplication revient dans ltat o il se trouvait au
moment o lapplication a affich la carte. Cela rsout les problmes dutilisation provoqus par la fermeture de lapplication, louverture de lapplication de cartographie, la
fermeture de celle-ci et le redmarrage de lapplication initiale.

iPhone Livre Page 137 Vendredi, 30. octobre 2009 12:04 12

Chapitre 6

Figure 6.2
Lapplication
MapExample place une
punaise sur chaque lieu.

Figure 6.3
Lapplication
MapExample affiche
une courte description.

Cartes Google

137

iPhone Livre Page 138 Vendredi, 30. octobre 2009 12:04 12

138

Dveloppez des applications pour liPhone

En invoquant la fonction JavaScript showMap du framework, lapplication embarque des


cartes. La Section 2 dtaille la conception et lutilisation de la classe Objective-C MapView
du framework, ainsi que dautres.

Section 2 : implmentation Objective-C du module


de cartographie de QuickConnect
Le module de cartographie de QuickConnect est constitu de trois classes :

MapView. Llment daffichage principal qui contient des images de la carte.

Pin. Une punaise qui doit tre affiche sur un lieu.

InfoWindow. Une classe utilise pour afficher la courte description associe une
punaise.

La Figure 6.4 illustre les relations entre ces classes. Chaque MapView peut avoir plusieurs
Pin, et chaque Pin doit avoir au moins un MapView. Il existe galement une relation un
un entre les Pin et les InfoWindow. Autrement dit, pour chaque Pin, il doit y avoir au
moins un InfoWindow et, pour chaque InfoWindow, il doit y avoir au moins un Pin.
Figure 6.4
Les classes du module
de cartographie et leurs
relations.

MapView

Pin

InfoView

tant modulaire par nature, une application Objective-C doit interagir directement avec la
classe MapView et son API, dont la seule mthode se nomme initWithFrame:andLocations. Lorsque cette mthode est invoque, une carte est gnre, des punaises sont
places et de courtes descriptions sont disponibles lutilisateur lorsquil touche une
punaise. Par ailleurs, si lutilisateur ralise un double-toucher sur une punaise ou un lieu
de la carte, laffichage est centr sur ce lieu et un zoom avant est effectu. Le code ci-aprs
montre comment cette API de MapView est employe dans le framework QuickConnect.
linstar de la localisation GPS, du dbogage et des autres requtes dcrites au Chapitre 2, lappel qui permet dafficher une carte embarque passe par un contrleur frontal et
des contrleurs dapplication. De mme, la commande showMap est associe showMapVCO dans le fichier QCCommandMappings.m. La mthode doCommand de ce VCO est
courte et consiste principalement placer les informations de latitude, de longitude et de
description passes dans un tableau par la requte JavaScript. Pour cela, le premier
lment du tableau parameters est cart, car il sagit du QuickConnectViewController

iPhone Livre Page 139 Vendredi, 30. octobre 2009 12:04 12

Chapitre 6

Cartes Google

139

de lapplication. La mthode doCommand, dont le code est donn ci-aprs, est extraite du
projet Xcode MapExample.
+ (id) doCommand:(NSArray*) parameters{
NSRange aRange = NSMakeRange(1, [parameters count]-1);
NSArray *locations = [parameters subarrayWithRange:aRange];
// Dimensionner le MapView la taille de lcran.
MapView *aMapView =
[[MapView alloc] initWithFrame:[[UIScreen mainScreen]applicationFrame]
andLocations:locations];
QuickConnectViewController *theController = [parameters objectAtIndex:0];
// Ajouter la vue de la carte la vue principale de lapplication.
[[[theController webView] superview] addSubview:aMapView];
return nil;
}

Puisque le QuickConnectViewController possde une rfrence au UIWebView qui affiche et excute lapplication, il permet dobtenir un pointeur sur sa vue principale. Pour
cela, le message superview est envoy au UIWebView. Le nouveau MapView est ensuite
ajout la vue principale de lapplication en le passant comme paramtre du message
addSubview. Aprs lenvoi de ce message, le MapView apparat et occupe lintgralit de
lcran en masquant le UIWebView.
Puisque MapView est un module autonome, sa fonctionnalit peut tre facilement rutilise
dans de nombreuses applications diffrentes (voir Chapitre 2 pour les questions de modularit). Il peut mme servir dans des applications Mac hybrides, aprs quelques modifications mineures la procdure daffichage de la carte.
Toutes les cartes Google, quel que soit le contenu affich, sont des pages web. Par consquent, lobjet MapView possde un attribut nomm webMapView qui correspond son
propre UIWebView. Il est diffrent de linstance de UIWebView qui affiche lapplication.
Comme le montre le code suivant, webMapView affiche le fichier mapView.html prsent
dans le groupe MapView des ressources, et son dlgu est la classe MapView. Le groupe
MapView comprend un UIView embarquable et un WebViewDelegate qui traite tous les
vnements pour le UIWebView.
1
2
3
4
5
6
7
8

(id)initWithFrame:(CGRect)frame
andLocations:(NSArray*)aLocationList {
if (self = [super initWithFrame:frame]) {
OKToTouch = NO;
self.locations = aLocationList;
frame.origin.y -= 20;
UIWebView *aWebView = [[UIWebView alloc]
initWithFrame:frame];

iPhone Livre Page 140 Vendredi, 30. octobre 2009 12:04 12

140

Dveloppez des applications pour liPhone

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 }

self.webMapView = aWebView;
[aWebView release];
aWebView.userInteractionEnabled = NO;
// Fixer le dlgu de la vue web la
// vue web elle-mme.
[aWebView setDelegate:self];
// Dterminer le chemin du fichier mapView.html qui
// se trouve dans le rpertoire des ressources.
NSString *filePathString =
[[NSBundle mainBundle] pathForResource:@"mapView" ofType:@"html"];
MESSAGE(@"%@", filePathString);
// Crer lURL et la requte pour
// le fichier mapView.html.
NSURL *aURL = [NSURL fileURLWithPath:filePathString];
NSURLRequest *aRequest =
[NSURLRequest requestWithURL:aURL];
// Charger le fichier mapView.html dans la vue web.
[aWebView loadRequest:aRequest];
// Ajouter la vue web la vue de contenu.
[self addSubview:self.webMapView];
}
return self;

Vous pourriez penser que, pour des raisons de simplicit, la classe MapView nest pas
ncessaire, mais ce nest pas vrai. Puisque le UIWebView capture tous les vnements de
toucher et ne permet pas ces vnements dtre traits par les lments HTML quil affiche,
le problme de dfilement dcrit la Section 1 apparat.
Pour rsoudre ce problme, la ligne 12 du code prcdent dsactive le traitement des
vnements par le UIWebView contenu. Cela permet lobjet MapView contenant dobtenir
tous les vnements en tant que dlgu. Le dlgu a ensuite la charge dindiquer au
UIWebView que la page quil contient doit tre dcale.
Pour faire dfiler une carte, il faut dterminer que le doigt de lutilisateur sest dplac
aprs le toucher. Pour cela, la mthode standard touchesMoved:withEvent de MapView
doit tre implmente.
-(void)touchesMoved:(NSSet *)touches
withEvent:(UIEvent *)event{
if(OKToTouch){
if([touches count] == 1){

iPhone Livre Page 141 Vendredi, 30. octobre 2009 12:04 12

Chapitre 6

Cartes Google

141

UITouch *touch = [touches anyObject];


CGPoint prevLoc = [touch previousLocationInView:self];
CGPoint curLoc = [touch locationInView:self];
double touchDeltaX = curLoc.x - prevLoc.x;
double touchDeltaY = curLoc.y - prevLoc.y;
NSString *javaScriptCall =
[[NSString alloc] initWithFormat:@"scroll(%f, %f)"
,touchDeltaX, touchDeltaY];
NSString *result = [webMapView
stringByEvaluatingJavaScriptFromString javaScriptCall];
if([result compare:@"true"] == 0){
int numPins = [pins count];
for(int i = 0; i < numPins; i++){
Pin *aPin = [pins objectAtIndex:i];
[aPin moveX:touchDeltaX andY:touchDeltaY];
[aPin.info moveX:touchDeltaX andY:touchDeltaY];
}
}
} else if([touches count] == 2){
// Pincement.
}
}
}

Cette implmentation de touchesMoved:withEvent commence par dterminer le mouvement du toucher. Pour cela, elle calcule la diffrence entre lemplacement de lvnement
courant et celui de lvnement prcdent. Le rsultat est pass la page HTML dans
webMapView en envoyant le message stringByEvaluatingJavaSCriptFromString avec
un appel la fonction JavaScript scroll.
Cette fonction, dont le code donn ci-aprs se trouve dans le fichier map.js du groupe
MapView, utilise lAPI JavaScript de cartographie de Google pour recentrer la partie visible de la carte. Elle applique les modifications ncessaires aux valeurs x et y du centre de
la carte et indique ensuite lobjet map de se centrer sur cette nouvelle position.
function scroll(deltaX, deltaY){
try{
var centerPoint = map.fromLatLngToDivPixel(map.getCenter());
centerPoint.x -= deltaX;
centerPoint.y -= deltaY;
var centerLatLng = map.fromDivPixelToLatLng(centerPoint);
map.setCenter(centerLatLng);
}

iPhone Livre Page 142 Vendredi, 30. octobre 2009 12:04 12

142

Dveloppez des applications pour liPhone

catch(error){
return false;
}
return true;
}

En cas de succs, cette fonction JavaScript retourne true afin que la suite de la mthode
touchesMoved:withEvent puisse demander chaque punaise affiche de changer de
position.
En raison de la capture dsactive sur le UIWebView sous-jacent, pour que le dfilement de
la carte puisse tre ralis, les punaises standard de Google ne sont pas en mesure de savoir
quelles ont t touches. Par consquent, les bulles de description ne peuvent pas tre affiches et masques pour ces punaises. Il est donc ncessaire de crer notre propre classe
Pin de gestion des punaises.
Cette classe, qui se trouve dans le groupe Classes:MapView, utilise limage pinInserted.png, dfinie dans Resources:Images, pour reprsenter les punaises lcran. Il est
trs facile de remplacer cette image par le fichier de votre choix.
Un objet de classe Pin est initialis pour chaque emplacement envoy par lapplication
depuis le ct JavaScript. Pour cela, la mthode initWithFrame:andImage:andLocation, dont le code est donn ci-aprs, est invoque. Elle cre un UIImageView pour
limage de la punaise, fixe son emplacement et active la capture des vnements en fixant
son attribut userInteractionEnabled true.
-(id)initWithFrame:(CGRect)frame
andImage:(NSString*)anImage
andLocation:(MapViewLocation)aLocation{
if (self = [super initWithFrame:frame]) {
UIImageView *pinImage = [[UIImageView alloc]
initWithImage:[UIImage imageNamed:anImage]];
[self addSubview:pinImage];
[pinImage release];
location = aLocation;
self.userInteractionEnabled = YES;
self.backgroundColor = [UIColor clearColor];
}
return self;
}

En permettant les interactions avec lutilisateur sur un objet Pin, la punaise peut intercepter
et traiter les vnements. Lorsquune punaise est touche, la mthode touchesBegan:withEvent de lobjet Pin est invoque et modifie laffichage.

iPhone Livre Page 143 Vendredi, 30. octobre 2009 12:04 12

Chapitre 6

Cartes Google

143

Cette fonction est dfinie dans le fichier Pin.m. Elle vrifie que les vnements actuel et
prcdent ont lieu au mme emplacement sur lcran. Ainsi, le code de cette mthode nest
pas excut lorsque lutilisateur fait glisser son doigt sur lcran avec un mouvement de
type balayement.
Si lon suppose que le balayement na pas lieu, deux cas sont pris en charge par touchesBegan:withEvent. Le premier correspond lutilisateur qui touche simplement la
punaise. Le comportement souhait consiste alors laffichage dun message simple, qui a
t envoy avec la position par la partie JavaScript de lapplication. Pour cela, le mcanisme de rflexion dObjective-C est utilis de manire envoyer un message singleTouch la punaise elle-mme.
Le message performSelector:withObject:afterDelay est envoy la punaise au lieu
deffectuer directement un appel. Cela permet de diffrencier un toucher simple dun
toucher double. Comme le montre la ligne 13, lutilisateur dispose de 0,4 seconde pour
effectuer un double-toucher. Si ce double-toucher ne se produit pas, le premier toucher est
captur et le second est trait comme un autre toucher.
En revanche, si lutilisateur effectue un double-toucher sur la punaise dans la limite
des 0,4 seconde, un message cancelPreviousPerformRequestsWithTarget:selector:
object est envoy de manire arrter le passage du message singleTouch. Cette solution dlai/excution ou annulation reprsente la mthode standard pour dtecter le nombre
de frappes dans les touchers.
Lorsquun toucher simple est dtect, le message singleTouch est pass et la description
courte associe la punaise est affiche. Dans le cas dun double-toucher, un zoom est
appliqu la carte et elle est centre sur lemplacement de la punaise.
1 -(void)touchesBegan:(NSSet *)touches
2
withEvent:(UIEvent *)event{
3
UITouch *touch = [touches anyObject];
4
CGPoint prevLoc = [touch previousLocationInView:self];
5
CGPoint curLoc = [touch locationInView:self];
6
7
if(CGPointEqualToPoint(prevLoc, curLoc)){
8
NSUInteger tapCount = [touch tapCount];
9
switch (tapCount) {
10
case 1:
11
[self performSelector:
12
@selector(singleTouch)
13
withObject:nil afterDelay:.4];
14
break;
15
case 2:
16
[NSObject cancelPreviousPerformRequestsWithTarget:self
17
selector:@selector(singleTouch)

iPhone Livre Page 144 Vendredi, 30. octobre 2009 12:04 12

144

Dveloppez des applications pour liPhone

18
19
20
21
22
23

object:nil];
// Zoom et centrage sur la punaise.
MESSAGE(@"double tap pin %i, %i",
location.x, location.y);
double latOffset = (location.y+42)/((MapView*)self.superview)
.pixelsPerDegLatitude;
double lngOffset = (location.x+10)/((MapView*)self.superview)
.pixelsPerDegLongitude;
double latitude = [[((MapView*)self.superview).northWest
objectAtIndex:0] doubleValue] - latOffset;
double longitude = [[((MapView*)self.superview).northWest
objectAtIndex:1] doubleValue] + lngOffset;
MESSAGE(@"latitude: %f longitude: %f northWest: %@",
latitude,
longitude,
((MapView*)self.superview).northWest);
NSString *javaScriptCall = [[NSString alloc] initWithFormat:
@"zoomTo(%f, %f)",latitude, longitude];
NSString *mapDescription = [((MapView*)self.superview).
webMapView stringByEvaluatingJavaScriptFromString:
javaScriptCall];

24
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
40
41
42 }

[((MapView*)self.superview) setMapLatLngFrameWithDescription:
mapDescription];
[((MapView*)self.superview) updatePinLocations];
break;
default:
break;
}
}

En autorisant le zoom et le centrage par un double-toucher sur une punaise ou sur la carte,
les possibilits dutilisation de lapplication sont tendues. Lapplication de cartographie
standard ne permet pas ce type de centrage par un double-toucher ; seul le zoom est mis en
uvre. Lorsque lutilisateur effectue un double-toucher, il le fait gnralement suivre dun
balayement pour afficher la rgion autour de la zone qui lintresse. Notre application ne
souffre pas de cet inconvnient.
Il est galement possible de dplacer les punaises sur la carte en les faisant glisser. Cela se
passe dans la mthode touchesMoved:withEvent, qui est comparable au dfilement de la
carte dcrit prcdemment. La diffrence rside dans le message cancelPreviousPerformRequestsWithTarget:selector:object, qui est de nouveau envoy de manire
viter laffichage de la description en raison de lappel la mthode touchesBegan avant

iPhone Livre Page 145 Vendredi, 30. octobre 2009 12:04 12

Chapitre 6

Cartes Google

145

celui de touchesMoved. Si le message dannulation nest pas envoy, la courte description


est affiche et la punaise est dplace. Lutilisateur risque de ne pas tre satisfait de ce
comportement.
1
2
3
4
5

-(void)touchesMoved:(NSSet *)touches
withEvent:(UIEvent *)event{
if([touches count] == 1){

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 }

[NSObject cancelPreviousPerformRequestsWithTarget:self selector:


@selector(singleTouch) object:nil];
moved = YES;
UITouch *touch = [touches anyObject];
CGPoint prevLoc = [touch previousLocationInView:self];
CGPoint curLoc = [touch locationInView:self];
double touchDeltaX = curLoc.x - prevLoc.x;
double touchDeltaY = curLoc.y - prevLoc.y;
[self moveX:touchDeltaX andY:touchDeltaY];
MapViewLocation mapLoc = self.location;
mapLoc.x += touchDeltaX;
mapLoc.y += touchDeltaY;
self.location = mapLoc;
if(self.info!= nil){
self.info.hidden = TRUE;
self.info.label.text = @"Unknown";
}
}

la manire du dfilement de la carte, le dplacement dune punaise se fonde sur les positions prcdente et actuelle pour mettre jour lemplacement. Dans le cas du dfilement
de la carte, lemplacement correspond au centre de la carte. Dans le cas du dplacement de
la punaise, il correspond au point daffichage suprieur gauche de la punaise et sa latitude
et sa longitude.
Puisque la punaise ne reprsente plus la position prcise lorigine sur la carte, la
description associe initialement la punaise est probablement invalide. Elle est par
consquent fixe Unknown. Par ailleurs, si le court message saffiche pendant que lutilisateur fait glisser la punaise, il est ferm de manire rduire la charge processeur impose par le trac de la punaise et du message pendant leur dplacement. Cette fermeture est
ralise la ligne 18.
Lattribut info de la classe Pin sert laffichage de la description fournie par la partie
JavaScript de lapplication. Il sagit dun objet InfoWindow qui est lui-mme un UIView
avec label pour seul attribut.

iPhone Livre Page 146 Vendredi, 30. octobre 2009 12:04 12

146

Dveloppez des applications pour liPhone

La mthode initWithFrame:andDescription de InfoWindow, donne ci-aprs et dfinie


dans le fichier InfoWindow.m prsent dans Classes:MapView, fixe lemplacement de la
fentre pour laffichage de la description. Llment dinterface employ pour afficher
cette description est un UILabel.
-(id)initWithFrame:(CGRect)frame
andDescription:(NSString*)description{
if (self = [super initWithFrame:frame]) {
[self setBackgroundColor:[UIColor blackColor]];
CGRect labelFrame = CGRectMake(0, 0,
frame.size.width,
frame.size.height);
label = [[UILabel alloc] initWithFrame:labelFrame];
label.text = description;
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor whiteColor];
label.textAlignment = UITextAlignmentCenter;
[self addSubview:label];
[label release];
}
return self;
}

En utilisant un UILabel pour afficher la description, les possibilits sont nombreuses.


Nous pouvons changer la police de caractres, son alignement, sa taille, sa couleur et bien
dautres attributs, comme les ombres portes. Nous pourrions dessiner le texte directement
au lieu dutiliser un UILabel, mais le code serait plus long. Grce au UILabel prdfini,
lapplication rsultante est plus facile maintenir.
Les trois classes MapView, Pin et InfoWindow forment le module MapView. Elles contiennent le code ncessaire laffichage dune carte Google de base, mais il est facile de les
modifier pour ajouter des comportements plus complexes.
Par exemple, vous pouvez modifier la classe InfoWindow pour quelle prsente dautres
dtails, soit en changeant sa taille daffichage, soit en affichant un autre UIView complet,
comme dans le cas de lapplication de cartographie dApple. Il est galement possible de
changer la classe MapView de manire obtenir des indications routires. Mme si ces
extensions requirent des connaissances en Objective-C, elles ne sont pas techniquement
difficiles.
Lajustement des positions de tous les objets Pin et de leur InfoWindow pendant le dfilement
ou le zoom de la carte est un autre point intressant que nous navons pas encore abord.
Chacune de ces classes possde une mthode moveX:andY. Elles prennent en paramtre le

iPhone Livre Page 147 Vendredi, 30. octobre 2009 12:04 12

Chapitre 6

Cartes Google

147

nombre de pixels, dans les directions x et y, ncessaires au dcalage de la punaise ou de la


fentre dinformation (voir le code ci-aprs).
Un programmeur Objective-C novice pourrait modifier la position par une ligne de code
comme [self frame].origin.x += xChange. Cette ligne ne lance aucune exception, ne
provoque aucune erreur de compilation, mais ne modifie pas la position de Pin ou de
InfoWindow.
Dans les classes Objective-C qui drivent de UIView, comme Pin et InfoWindow, le cadre
qui reprsente la position suprieure gauche, ainsi que la largeur et la hauteur, est appliqu
uniquement dans deux cas. Le premier correspond son initialisation avec le message
initWithFrame. Dans ce cas, la structure du cadre fournie en paramtres est utilise pour
dimensionner la vue. Le second correspond au remplacement de lattribut frame par un
autre, comme dans la mthode moveX:andY suivante.
- (void) moveX:(double) xChange andY:(double)yChange{
CGRect frame = [self frame];
frame.origin.x += xChange;
frame.origin.y += yChange;
self.frame = frame;
}

En raison de cette limitation, la manipulation de lattribut frame de la vue na aucun effet.


La mthode moveX:andY doit tre appele pour chaque dfilement ou zoom de la carte.
Dans la mthode touchesMoved:withEvent de la classe MapView, chaque punaise reoit
ce message lors de la capture dun vnement.
for(int i = 0; i < numPins; i++){
Pin *aPin = [pins objectAtIndex:i];
[aPin moveX:touchDeltaX andY:touchDeltaY];
[aPin.info moveX:touchDeltaX andY:touchDeltaY];
}

La mthode touchesEnded:withEvent de la place MapView prend en charge le zoom de


la carte. Ce message est envoy par lappareil un objet MapView aprs le traitement de
tous les messages touchesBegan et touchesMoved.
Dans le code suivant, vous remarquerez quaprs avoir tabli quil sagit dun doubletoucher la position du toucher sur la carte est dtermine. Ensuite, la fonction JavaScript
zoomTo est appele, comme dans le cas du zoom dune punaise.
1
2
3

-(void)touchesEnded:(NSSet *)touches
withEvent:(UIEvent *)event{

iPhone Livre Page 148 Vendredi, 30. octobre 2009 12:04 12

148

Dveloppez des applications pour liPhone

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

if(OKToTouch){
UITouch *touch = [touches anyObject];
if ([touch tapCount] == 2){
// Zoom et centrage.
CGPoint curLoc = [touch locationInView:self];
double latOffset = curLoc.y/self.pixelsPerDegLatitude;
double lngOffset = curLoc.x/pixelsPerDegLongitude;
double latitude = [[northWest objectAtIndex:0] doubleValue] - latOffset;
double longitude = [[northWest objectAtIndex:1] doubleValue] + lngOffset;
NSString *javaScriptCall = [[NSString alloc] initWithFormat:
@"zoomTo(%f, %f)",latitude, longitude];
NSString *mapDescription = [webMapView stringByEvaluatingJava
ScriptFromString:javaScriptCall];

16
17
18
19
20
21
22
23
24
25 }

[self setMapLatLngFrameWithDescription:mapDescription];
[self updatePinLocations];
}
else{
NSLog(@"toucher");
}
}

Une fois le zoom termin, que ce soit dans le cas dun double-toucher pour lobjet Pin ou
MapView, un message updatePinLocations est envoy lobjet MapView (ligne 19 du
code prcdent). Le code suivant montre que cet appel provoque la mise jour de la position de chaque punaise en fonction de sa latitude, de sa longitude et du facteur de zoom de
la carte.
Le facteur de zoom est reprsent par les attributs pixelsPerDegLatitude et pixelsPerDegLongitude de la classe MapView fixs lors dun appel prcdent la mthode setMapLatLngFrameWithDescription.
1
2
3
4
5
6
7
8
9

-(void) updatePinLocations{
int numPins = [pins count];
for(int i = 0; i < numPins; i++){
Pin *aPin = (Pin*)[pins objectAtIndex:i];
double latitudeDelta = [[northWest objectAtIndex:0] doubleValue] aPin.location.latitude;
double longitudeDelta = aPin.location.longitude - [[northWest
objectAtIndex:1] doubleValue];
double yPixels = latitudeDelta * pixelsPerDegLatitude;
double xPixels = longitudeDelta * pixelsPerDegLongitude;

iPhone Livre Page 149 Vendredi, 30. octobre 2009 12:04 12

Chapitre 6

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

Cartes Google

149

MapViewLocation aPinLocation = aPin.location;


aPinLocation.x = xPixels - 10 - 4;
// Le visuel de la punaise se trouve dans limage 10pixels
// partir de la gauche.
aPinLocation.y = yPixels - 42 + 10;
// Le visuel de la punaise se trouve dans limage 10pixels
// partir du bas.
CGRect pinFrame = aPin.frame;
pinFrame.origin.x = aPinLocation.x;
pinFrame.origin.y = aPinLocation.y;
aPin.frame = pinFrame;
aPin.location = aPinLocation;
CGRect infoFrame = aPin.info.frame;
infoFrame.origin.x = aPinLocation.x - 100;
infoFrame.origin.y = aPinLocation.y - 30;
aPin.info.frame = infoFrame;
}

Comme dans la mthode moveX:andY, le cadre doit tre retrouv, modifi et initialis. Ces
oprations sont ralises aux lignes 18 22 du code prcdent pour la punaise et aux
lignes 24 27 pour le InfoWindow associ lobjet Pin.
La position des objets Pin et InfoWindow est mise jour lors de chaque zoom. Il est possible que certains dentre eux ne soient plus dans les limites de visibilit fixes par le
MapView courant, mais ce nest pas un problme. Ils sont simplement affichs dans une
partie non visible, en dehors de lcran. Le code na pas besoin de les masquer.

En rsum
Ce chapitre a expliqu comment embarquer des cartes Google dans une application et
comment le module daffichage dune carte a t cr. Il a galement montr comment
manipuler les positions des vues personnalises et des vues standard.
En utilisant judicieusement lAPI JavaScript de Google avec une carte affiche par un
UIWebView, il est possible deffectuer un zoom et un recentrage.
Puisque toutes ces fonctionnalits sont incluses dans le framework QuickConnect, il vous
suffit dun seul appel JavaScript pour afficher une carte Google pleinement oprationnelle.
Si le ct JavaScript du framework est simple dutilisation, il est galement facile dutiliser le module de cartographie dans nimporte quelle application Objective-C pour
liPhone. En ralit, seules quelques lignes de code sont ncessaires.

iPhone Livre Page 150 Vendredi, 30. octobre 2009 12:04 12

150

Dveloppez des applications pour liPhone

Les cartes Google personnalises peuvent dsormais tre embarques dans nimporte
quelle application pour liPhone. La version 3.0 du systme dexploitation de liPhone
rend mme cette fonctionnalit encore plus facile.

iPhone Livre Page 151 Vendredi, 30. octobre 2009 12:04 12

7
Bases de donnes
La plupart des applications crites en JavaScript ont besoin dun serveur web pour enregistrer des donnes. Depuis la version 2.0 du systme dexploitation de liPhone et sa classe
UIWebView, il est possible denregistrer des donnes sur le tlphone sans passer par le
rseau. Autrement dit, lapplication que vous crez est une entit de premire classe sur
liPhone. Ce chapitre explique comment enregistrer et retrouver des donnes, et comment
crer des bases de donnes et des tables. Il fournit une enveloppe JavaScript simple
demploi pour accder la base de donnes SQLite disponible sur liPhone. Les premires
sections dcrivent lutilisation de la base de donnes, les dernires prsentent le code de
lenveloppe.

Section 1 : application BrowserDBAccess


Lapplication BrowserDBAccess a t cre pour vous aider comprendre lutilisation des
bases de donnes dans les applications JavaScript. Elle cre une base de donnes SQLite
nomme sampleDB, dans laquelle une table, score, est dfinie. Cette base de donnes
existe dans le UIWebView et lutilisateur peut la consulter. Les bases de donnes cres de
cette manire sont persistantes entre les excutions de lapplication, mme si elles nont pas
t installes avec lapplication. Cette dernire peut ainsi retrouver les donnes enregistres

iPhone Livre Page 152 Vendredi, 30. octobre 2009 12:04 12

152

Dveloppez des applications pour liPhone

dans la base chaque excution. La Figure 7.1 montre lexcution de cette application
avant lenvoi dune requte la base de donnes.
Figure 7.1
Lapplication
BrowserDBAccess avant
lexcution de la requte.

La table score de lapplication BrowserDBAccess comprend deux champs. Le premier,


de type caractre nomm player_name, correspond la cl primaire. Le second, nomm
score, est de type entier. Puisque la cl primaire nest pas incrmente automatiquement,
sa valeur doit tre fournie chaque fois quun enregistrement est ajout. BrowserDBAccess
utilise plusieurs classes, mthodes et fonctions JavaScript prdfinies pour accder aux
donnes de sampleDB.

Terminologie des bases de donnes


Le monde des bases de donnes possde sa propre terminologie. Les tables servent
regrouper des lments semblables. Chacun de ces lments est appel enregistrement.
Les enregistrements sont constitus de valeurs saisies dans des champs. Les champs sont
dfinis par leur nom et leur type. Les enregistrements sont comparables aux lignes dune
feuille de calcul, les champs, aux colonnes. Les tables sont les feuilles de calcul. Si vous
ajoutez un nouvel enregistrement une table chiens, cela quivaut ajouter une
nouvelle ligne une feuille de calcul chiens. En ralit, ce nest pas vraiment identique,
mais suffisamment comparable pour faciliter la comprhension.

iPhone Livre Page 153 Vendredi, 30. octobre 2009 12:04 12

Chapitre 7

Bases de donnes

153

Une cl primaire identifie de manire unique chaque enregistrement dune table. Il peut
sagir dun entier ou dune chane de caractres, mais les doublons sont interdits. Une cl
primaire peut correspondre, par exemple, la combinaison de votre nom dutilisateur et
de votre mot de passe ADC (Apple Developer Connection). Bien videmment, si deux
personnes avaient les mmes informations douverture de session, le rsultat serait
dramatique.
Une cl trangre est un autre lment. Elle est utilise pour lier des donnes enregistres
dans deux tables diffrentes. Imaginez les deux tables propritaires et chiens. La table
propritaires possde une cl primaire pour chaque enregistrement. Pour lier les chiens
et les propritaires, une cl trangre est ajoute la table chiens. Cette cl trangre
contient la cl primaire du propritaire dun chien dans la table propritaires. Cela quivaut au numro didentification tatou dans loreille du chien et qui permet de retrouver
son propritaire.

Section 2 : utilisation des bases de donnes SQLite


avec WebView
Lutilisation des bases de donnes peut paratre intimidante. Un programmeur doit garder
lesprit toute une ribambelle de piges potentiels lors de lenregistrement ou de lobtention des informations. En raison de ces cueils, les programmeurs choisissent souvent de
ne pas employer des bases de donnes pour le stockage de donnes simples.
Sur liPhone, la solution native pour le stockage des donnes des applications passe par
une base de donnes SQLite embarque, non un fichier texte ou binaire. La rapidit et la
facilit dutilisation de ce moteur de bases de donnes peut conditionner le succs de vos
applications. Pour acclrer le dveloppement, le framework QuickConnectiPhone
propose une classe JavaScript qui vous vite tous les tracas associs lutilisation des
bases de donnes.
Le fichier DataAccessObject.js, prsent dans le groupe QCiPhone des modles Dashcode
et Xcode, contient une enveloppe qui prend en charge laccs la base de donnes SQLite.
Les deux modles incluent automatiquement ce fichier JavaScript dans le fichier
index.html de lapplication. La classe DataAccessObject dfinie par lenveloppe
comprend un constructeur et quatre mthodes (voir Tableau 7.1).
Cette classe JavaScript est employe dans le fichier databaseDefinition.js inclus dans votre
application par les modles. Cest dans ce fichier que vous devez indiquer la ou les bases
de donnes utilises par votre application.
Le code suivant, extrait du fichier databaseDefinition.js de lapplication BrowserDBAccess,
montre comment utiliser le constructeur pour crer une base de donnes gre par le

iPhone Livre Page 154 Vendredi, 30. octobre 2009 12:04 12

154

Dveloppez des applications pour liPhone

Tableau 7.1 : API de DataAccessObject

Attribut/mthode

Valeur de retour

DataAccessObject
DataAccess(dbName, dbVersion,
Object
dbDescription, dbSize)

Description

Paramtres

Cre un Data-

dbName une chane


diden-tification unique
employe pour dsigner la
base de donnes.

AccessObject
lorsquelle est
appele avec le mot
cl new.

dbVersion une chane


donne gnralement sous
forme dun nombre virgule
flottante.
dbDescription une
chane prcisant le rle de la
base de donnes.
dbSize la quantit minimale despace disque allou
la base de donnes (en
octets). Si ce paramtre est
absent ou si null est pass, la
taille par dfaut est utilise
(5 Mo).

getData(SQL,
parameterArray)

setData(SQL,
parameterArray)

Aucune

Aucune

Cette mthode
permet dextraire
les informations,
conformment
linstruction SQL
passe, partir
dune base de
donnes cre dans
UIWebView.

SQL une chane de commande SQL valide.

Cette mthode
permet denregistrer des informations, conformment linstruction
SQL passe, dans
une base de donnes
cre dans
UIWebView.

SQL une chane de commande SQL valide.

parameterArray un
tableau des valeurs utilises
par la commande SQL
dans le cas dune instruction
prpare.

parameterArray un
tableau des valeurs utilises
par la commande SQL
dans le cas dune instruction
prpare.

iPhone Livre Page 155 Vendredi, 30. octobre 2009 12:04 12

Chapitre 7

Bases de donnes

155

Tableau 7.1 : API de DataAccessObject (suite)

Attribut/mthode

Valeur de retour

Description

Paramtres

getNativeData(SQL,
parameterArray)

Aucune

Cette mthode
permet dobtenir des
informations partir
dune base de donnes installe avec
lapplication.

SQL une chane de commande SQL valide.

Cette mthode
permet denregistrer
des informations
dans une base de
donnes installe
avec lapplication.

SQL une chane de commande SQL valide.

setNativeData(SQL,
parameterArray)

Aucune

parameterArray un
tableau des valeurs utilises
par la commande SQL
dans le cas dune instruction
prpare.

parameterArray un
tableau des valeurs utilises
par la commande SQL
dans le cas dune instruction
prpare.

moteur WebKit dans les applications hybrides pour liPhone. Lutilisation du moteur de
base de donnes intgr au moteur se rvle approprie lorsque toutes les donnes sont
gnres par lapplication aprs son installation.
var sampleDatabase = new DataAccessObject("sampleDB", "1.0", "a sample database ",2000);

Le code prcdent cre une base de donnes nomme sampleDB, ou louvre si elle existe
dj. Puisque WebKit prend en charge la cration et lutilisation de cette base de donnes,
il a besoin de deux lments dinformation. Le premier est le numro de version de la
base. Vous pouvez choisir nimporte quelle valeur ; dans notre exemple, il est fix 1.0.
Le second indique la taille maximale prvue de la base de donnes ; dans notre exemple, il
est fix 2000 octets.
La valeur retourne par lappel au constructeur est un DataAccessObject connect la
base de donnes SQLite sous-jacente et prt tre utilis. La modification de la base de
donnes est ensuite possible, comme le montre le code suivant, qui utilise la mthode
setData de DataAccessObject.
sampleDatabase.setData("CREATE TABLE IF NOT EXISTS score (player_name VARCHAR
PRIMARY KEY, score INTEGER);");

iPhone Livre Page 156 Vendredi, 30. octobre 2009 12:04 12

156

Dveloppez des applications pour liPhone

La commande SQL correspond la cration dune table, mais la mthode setData est
employe pour toutes les requtes SQL qui modifient les tables de la base, ajoutent ou
suppriment des donnes, ou modifient la base dune manire ou dune autre.
Nous lavons dcrit au Chapitre 2, les fonctions de contrle mtier (BCF, Business Control
Function) peuvent tre utilises pour obtenir des donnes partir de la base. Cest prcisment le rle de la BCF getScoresBCF (voir ci-aprs) ; vous la trouverez dans le fichier
functions.js.
Cette BCF se fonde sur la mthode getData de DataAccessObject pour obtenir des enregistrements partir de la table score. Lappel correspondant se trouve la ligne 3.
1 function getScoresBCF(parameters){
2
var SQL = SELECT * FROM score;
3
sampleDatabase.getData(SQL);
4 }

La Figure 7.2 illustre les donnes obtenues via cette BCF. Notez que getScoresBCF ne
retourne aucune valeur, car la mthode getData est asynchrone. Le framework QuickConnectiPhone prend en charge la rception des donnes rsultantes de la requte SQL et les
passe aux objets de contrle associs la mme commande que la BCF. La fonction de
contrle de laffichage displayScoresVCF, dfinie dans le fichier functions.js, est associe la mme commande que getScoresBCF. Par consquent, le framework lui passe les
informations ds quelles sont disponibles.
Linsertion de donnes dans la table se fait de manire comparable. Pour insrer lenregistrement de la personne nomme Jane, la mthode setData doit tre appele de la manire
suivante :
sampleDatabase.setData("INSERT INTO score VALUES(Jane, 250)");

Les valeurs ne sont gnralement pas figes dans les instructions SQL. Le plus souvent,
elles sont saisies par lutilisateur. Bien quil soit possible de construire une instruction
SQL comme la prcdente partir des informations fournies par lutilisateur, cette solution est dangereuse. Le code suivant montre comment viter ce danger laide des instructions
prpares.
function setScoresBCF(parameters){
var name = document.getElementById(nameField).value;
var score = document.getElementById(scoreField).value;
var statementParameters = [name, score];
var SQL = "INSERT INTO score VALUES(?,?)";
sampleDatabase.setData(SQL, statementParameters);
}

iPhone Livre Page 157 Vendredi, 30. octobre 2009 12:04 12

Chapitre 7

Bases de donnes

157

Figure 7.2
Lapplication
BrowserAccessExample
aprs avoir touch le
bouton Excuter la
requte.

Vous remarquerez quil diffre du code qui appelle setData pour crer la table score.
Dans la chane SQL, des points dinterrogation ont remplac le nom et le score qui taient
supposs apparatre. Il sagit de paramtres substituables employs dans les instructions
prpares pour indiquer o doivent tre insres les donnes du tableau statementParameters. Le programmeur se charge dajouter au tableau les valeurs qui seront places,
dans lordre, dans la chane SQL. Cest pourquoi la variable name est ajoute au tableau
statementParameters avant la variable score.

Instructions prpares
Les instructions prpares amliorent normment la scurit des instructions SQL servant
enregistrer les donnes saisies par lutilisateur. En ralit, elles constituent un bon
moyen darrter les attaques par injection SQL et devraient tre utilises plus quelles ne
le sont actuellement.
Supposons que vous vouliez ajouter un enregistrement une table nomme
preferences_utilisateur, qui comprend les champs lieu, couleur et chanson. Vous pourriez
procder de la manire suivante :
"SELECT * FROM preferences_utilisateur WHERE nom = "+unNom

Cette manire de composer les instructions SQL est mauvaise, vraiment trs mauvaise. Elle
ouvre la porte aux attaques par injection SQL sur lintgralit de la base de donnes.

iPhone Livre Page 158 Vendredi, 30. octobre 2009 12:04 12

158

Dveloppez des applications pour liPhone

Ces attaques permettent de pntrer dans les bases de donnes. Vous ne devez pas
composer les instructions SQL de cette manire.
Pour crer une chane SQL, voici la solution scurise :
"SELECT * FROM preferences_utilisateur WHERE nom =?)"

Vous devez galement crer un tableau qui contient les valeurs qui seront utilises la
place des points dinterrogation. Puisquelles se fondent sur une instruction prpare, les
appels setData et getData soccupent du reste.
Lorsquune instruction prpare est utilise, la chane SQL est analyse avant que les
points dinterrogation ne soient remplacs par les valeurs. Autrement dit, toute
commande SQL malveillante place dans les variables est dtecte et rejete ; pour la
base de donnes, linstruction SQL semble contenir une chane trange. Un appel avec des
points dinterrogation, tel que le prcdent, ne retourne aucun rsultat. En revanche, en
composant linstruction SQL par concatnation, un hacker peut facilement obtenir tout ce
quil souhaite partir dune table.

Les instructions prpares protgent les bases de donnes des intrusions connues sous le
nom attaques par injection SQL. Mme sil peut sembler idiot de protger notre petite base
de donnes contre les intrusions, ce nest pas le cas. Si quelquun russit obtenir un accs
non autoris un appareil ou au code qui sy excute, il trouvera toujours le moyen de
causer des dommages. Tous les dveloppements doivent se faire de manire scurise.
La suppression de donnes dans la base suit une procdure comparable. Puisque la base de
donnes est modifie, la mthode setData est employe. Puisque lutilisateur saisit le
nom supprimer, une instruction prpare est utilise.
function deleteScoreBCF(parameters){
var name = document.getElementById(nameField).value;
var statementParameters = [blogName];
database.setData(DELETE FROM score where name =?,
statementParameters);
}

Section 3 : utilisation de bases de donnes SQLite


natives
Outre la possibilit de crer et dutiliser des bases de donnes dans le moteur WebKit
disponible dans toute application hybride pour liPhone, il est galement possible dutiliser des bases de donnes natives. Grce ces bases de donnes, les dveloppeurs dapplications peuvent inclure des donnes existantes dans lapplication installe. Par exemple,

iPhone Livre Page 159 Vendredi, 30. octobre 2009 12:04 12

Chapitre 7

Bases de donnes

159

vous pourriez inclure dans votre application tout un ensemble de localisations GPS standard afin daider les utilisateurs trouver des produits sur un march de vente au dtail. Au
lieu de tlcharger et denregistrer les donnes au dmarrage de lapplication, vous pouvez
fournir un fichier de base de donnes SQLite avec votre application.
Dun point de vue fonctionnel, lapplication nativeDBAccess est identique BrowserDBAccess, mais elle utilise un fichier de base de donnes SQLite nomm sample.sqlite. La
Figure 7.3 montre la prsence de ce fichier dans le groupe Resources du projet Xcode.

Figure 7.3
Les ressources de lapplication nativeDBAccess.

Le code JavaScript ncessaire la cration dun DataAccessObject qui enveloppe les


appels une base de donnes native diffre de celui de la Section 2 employ avec les bases
de donnes du moteur WebKit. Si la dfinition de la base de donnes se fait toujours dans
le fichier databaseDefinition.js, dans le cas des bases de donnes natives seul le nom du
fichier de base de donnes est indiqu. Les paramtres de version et de taille sont superflus, car les bases de donnes natives ont une taille illimite (avec raison) et la gestion des
versions fait partie du processus de construction et de distribution de lapplication.
var sampleDatabase = new DataAccessObject("sample.sqlite");

iPhone Livre Page 160 Vendredi, 30. octobre 2009 12:04 12

160

Dveloppez des applications pour liPhone

Notez quaucun appel ne cre une table, car la table score existe dj dans le fichier
sample.sqlite. Bien quil soit possible de crer des tables dans des bases de donnes natives, cette opration est inhabituelle. Les tables sont gnralement ajoutes aux fichiers de
base de donnes avant la distribution de lapplication sur lApp Store.
Pour obtenir des donnes depuis une base native, la mthode est pratiquement identique
celle mise en place pour les bases de donnes WebKit. La seule diffrence, illustre dans le
code suivant, est que la mthode getData est remplace par la mthode getNativeData.
Pour le dveloppeur de lapplication, ces deux mthodes ont un comportement identique.
function getScoresBCF(parameters){
debug(Obtention des scores depuis la base de donnes);
var SQL = SELECT * FROM score;
sampleDatabase.getNativeData(SQL);
}

De mme que getData dcrite la Section 2, la mthode getNativeData est asynchrone. Par consquent, ds que les donnes sont disponibles, le framework les passe
aux objets de contrle associs la mme commande que la BCF, dans ce cas
displayScoresVCF. La Figure 7.4 prsente la page gnre par cette VCF dans lapplication nativeDBAccess.
Figure 7.4
Lapplication
nativeDBAccess aprs
avoir touch le bouton
dexcution de la requte.

iPhone Livre Page 161 Vendredi, 30. octobre 2009 12:04 12

Chapitre 7

Bases de donnes

161

Lajout et la suppression des donnes, ainsi que la modification de la base de donnes, se


font exactement de la mme manire qu la Section 2, except que la mthode setNativeData est invoque la place de la mthode setData. En tant que dveloppeur de lapplication,
les diffrences de comportements vous sont transparentes.

Section 4 : utilisation de DataAccessObject


avec les bases de donnes du moteur WebKit
Les sections prcdentes ont expliqu comment utiliser DataAccessObject pour manipuler des bases de donnes SQLite WebKit ou natives, sans avoir connatre leurs dtails de
fonctionnement internes. Cette section rvle ces dtails et montre comment les utiliser. Si
vous souhaitez simplement exploiter DataAccessObject, sans volont den connatre le
fonctionnement, vous pouvez sauter cette section.
Grce la classe DataAccessObject, dfinie dans le fichier DataAccessObject.js du
groupe QCiPhone, le programmeur nest pas oblig de possder des connaissances dtailles
quant SQLite. Elle a t conue avec des mthodes et des constructeurs comparables
ceux de lenveloppe AJAX ServerAccessObject dcrite au Chapitre 8. En simplifiant
lAPI, les programmeurs qui ne sont pas familiers de SQLite ont la possibilit denregistrer
des donnes sans passer par une longue phase dapprentissage.
Le constructeur de DataAccessObject est la plus simple de toutes ces mthodes. Il fixe et
dfinit les mthodes de lobjet comme des fonctions anonymes. Autrement dit, aucun attribut nest ncessaire pour enregistrer les paramtres passs au constructeur.

Fonctions anonymes
Lorsque quelquun est anonyme, cela signifie que vous ne connaissez pas son nom.
Lorsquune fonction est anonyme, cela signifie quelle na pas de nom. En JavaScript, une
fonction standard a un nom dclar laide dune ligne semblable la suivante :
function aboyer(){}

Dans ce cas, la fonction se nomme aboyer. Lorsquune fonction doit tre passe une
autre fonction, il est frquent demployer des fonctions sans nom dclar. Ces fonctions
sont anonymes.
Pour passer une fonction anonyme aboyer, nous utilisons le code suivant :
aboyer(new function(){
// Faire quelque chose ici.
});

iPhone Livre Page 162 Vendredi, 30. octobre 2009 12:04 12

162

Dveloppez des applications pour liPhone

Notez que les oprateurs de porte de la fonction anonyme, {}, sont contenus dans les
oprateurs de paramtre de la fonction aboyer, (). La fonction aboyer peut invoquer ou
enregistrer cette fonction comme bon lui semble.
Les fonctions anonymes ont accs aux variables locales dfinies dans la fonction dans
laquelle elles ont t dclares. Par consquent, le code suivant est valide :
String type = doberman;
aboyer(new function(){
if(type == boxer){
}
else if(type == doberman){
}
...
});

Cette possibilit est pratique lorsque des fonctions ou des mthodes prennent des fonctions en paramtres, comme nous le verrons plus loin dans cette section.
linstar de nombreux outils puissants, il est important de ne pas faire un usage excessif
des fonctions anonymes si elles ne sont pas ncessaires.

Nous avons vu au Tableau 7.1 et aux Sections 2 et 3 que DataAccessObject comprend


deux principaux groupes de mthodes. Lun prend en charge les donnes enregistres ou
obtenues avec une base de donnes WebKit, tandis que lautre soccupe des transferts
entre la partie JavaScript de lapplication et un fichier de base de donnes SQLite fourni.
Les mthodes fondes sur WebKit utilisent principalement du code JavaScript et sont
examines en premier.
Les mthodes getData et setData sont des faades. Elles contiennent peu de code et se
fondent sur une troisime mthode pour raliser la plus grande partie du travail. Leur seule
tche vritable consiste assembler les valeurs enregistres dans la variable passThroughParameters.
this.getData = function(SQL, preparedStatementParameters){
var passThroughParameters = generatePassThroughParameters();
this.dbAccess(SQL, preparedStatementParameters,
false, passThroughParameters);
}

Puisque le comit de normalisation du W3C responsable des spcifications HTML 5 exige


que tous les appels aux fonctionnalits de base de donnes du moteur WebKit soient asynchrones, certaines informations concernant ltat courant de lapplication doivent tre

iPhone Livre Page 163 Vendredi, 30. octobre 2009 12:04 12

Chapitre 7

Bases de donnes

163

passes avec les requtes pour quelles puissent tre utilises par la suite. La fonction
generatePassThroughParameters, dfinie dans QCUtilities.js, runit ces valeurs.
Le code suivant montre que cela inclut la commande courante pour laquelle des objets de
commandes sont invoqus, le nombre de BCO dj appels, les paramtres passs toutes
les fonctions de contrle, comme globalParamArray, et un tableau contenant tous les
rsultats dj gnrs par les appels dautres BCF, comme globalBCFResults.
function generatePassThroughParameters(){
var passThroughParameters = new Array();
passThroughParameters.push(window.curCmd);
passThroughParameters.push(window.numFuncsCalled);
passThroughParameters.push(globalParamArray);
passThroughParameters.push(window.globalBCFResults);
return passThroughParameters;
}

Ces valeurs servent ensuite au framework pour garantir que les autres fonctions de
contrle associes la commande curCmd dans le fichier mappings.js sont excutes
comme si tous les appels taient synchrones. Pour de plus amples informations concernant
cette procdure, consultez le Chapitre 2.
Le tableau passThroughParameters est transmis la mthode dbAccess, avec un indicateur qui prcise si les instructions contenues dans la variable SQL doivent tre traites
comme une modification des donnes dans la base. Dans la mthode getData, cet indicateur
est false.
La mthode dbAccess est au cur de la classe DataAccessObject pour les bases de
donnes du moteur WebKit. Elle effectue tout le travail demand par les appels getData
et setData.
Pour comprendre cette mthode, il faut tout dabord comprendre lAPI JavaScript sousjacente de SQLite. Cette API fait partie du standard HTML 5 venir et est implmente
dans le moteur WebKit employ par le UIWebView de toutes les applications hybrides pour
liPhone et le navigateur Mobile Safari. La dernire version de ce standard est disponible
ladresse http://www.w3.org/html/wg/html5/#sql. Ce document dcrit plusieurs objets et
mthodes recenss dans les tableaux suivants.
Database constitue llment de base de cette API. Le Tableau 7.2 dcrit une fonction
associe cet objet et lune de ces mthodes. openDatabase est une fonction de fabrique
qui instancie un objet Database notre place.
Selon le document de normalisation, tous les paramtres de openDatabase sont facultatifs.
Toutefois, il est peu judicieux de ne pas dclarer un nom de base de donnes. Si vous utilisez plusieurs bases de donnes dans diffrentes applications, chacune doit possder un

iPhone Livre Page 164 Vendredi, 30. octobre 2009 12:04 12

164

Dveloppez des applications pour liPhone

Tableau 7.2 : API de Database

Attribut/mthode

Valeur de retour

Description

Paramtres

openDatabase
(dbName, dbVersion,
dbDescription, dbSize)

Objet Database

Une fonction de fabrique


qui cre un objet Database en vue de son utilisation ultrieure.

dbName une chane


didentification unique
employe pour dsigner
la base de donnes.

dbVersion une
chane, gnralement
donne sous forme dun
nombre virgule flottante.
dbDescription une
chane prcisant lobjectif de la base de donnes.
dbSize la quantit
minimale despace disque allou la base de
donnes (en octets). Si ce
paramtre est absent ou si
null est pass, la taille
par dfaut est utilise
(5 Mo).

transaction(executionCallback, errorCallback,
successCallback)

Objet SQLTran-

saction

Cette mthode cre un


objet SQLTransaction
utilis pour les mises
jour et les requtes sur la
base de donnes.

executionCallback
une fonction qui contient
le code ncessaire
lexcution du SQL.

errorCallback une
fonction facultative qui
est appele lorsque la
transaction a chou.
Lannulation des oprations sur la base de donnes nest pas effectue
dans cette mthode, car
cette procdure est automatique en cas dchec.
successCallback
une fonction facultative
qui est appele lorsque la
transaction a russi.

iPhone Livre Page 165 Vendredi, 30. octobre 2009 12:04 12

Chapitre 7

Bases de donnes

165

nom distinct. Si dbName reste vide, il est possible quune mme base de donnes soit partage par toutes les applications. Elle risque donc de subir les oprations malencontreuses
des applications crites par dautres programmeurs. Pour protger vos bases de donnes,
vous devez utiliser une rgle comparable celle de la mme origine qui contraint les
appels AJAX dans un navigateur.
Cette rgle de protection applique aux bases de donnes stipule que seules les applications ayant la mme origine peuvent accder une base de donnes. Si vous utilisez des
bases de donnes dans des applications web hberges sur www.monsite.fr et sur
web.monsite.fr, ces bases sont accessibles par les diffrentes applications web. Autrement dit, toutes les applications qui proviennent de monsite.fr peuvent accder toutes
les bases de donnes qui ont cette origine, quelle que soit lapplication qui a cr la base
de donnes, mme dans un sous-domaine de monsite.fr.
Dans les applications hybrides, lobjet UIWebView remplace le navigateur web et, par
consquent, il nexiste aucune rgle de mme origine qui limite les requtes AJAX. Cela
nest pas encore tabli, mais nous pouvons supposer que la restriction de mme origine sur
les bases de donnes nest pas plus effective. Cest pourquoi la seule protection de votre
base de donnes contre les accs par dautres applications rside dans lutilisation dun
nom et dune version inconnus des autres programmeurs. Vous devez donc donner un nom
et une version votre base de donnes.
La mthode transaction est employe par tous les appels SQL. En ralit, il est impossible dexcuter des instructions SQL sur des bases de donnes WebKit sans passer par un
objet SQLTransaction cr par la mthode transaction. Par consquent, dans les applications hybrides pour liPhone, tous les appels JavaScript concernant une base de donnes
sont automatiquement transactionnels.
Les dveloppeurs sont souvent proccups par lannulation des oprations sur la base de
donnes. En gnral, cette annulation est effectue lorsque le code crit par le programmeur dtecte lchec dune transaction. Lorsque vous utilisez les fonctionnalits JavaScript de base de donnes, ces annulations ne constituent pas un problme car les
transactions sen occupent automatiquement en cas dchec.
Vous ne devez pas excuter une instruction SQL ROLLBACK en cas dchec dune transaction. Cette opration a dj t effectue et cela risque de provoquer des dysfonctionnements. La fonction errorCallBack passe la mthode transaction nest pas utilise
dans ce but. Elle sert uniquement signaler les checs.
Lobjet SQLTransaction noffre quune seule mthode, executeSQL (voir Tableau 7.3).
Elle accepte toute instruction SQL que vous lui passez, mais il est imprudent dassembler une instruction SQL et de lexcuter. Vous devez utiliser la place les instructions

iPhone Livre Page 166 Vendredi, 30. octobre 2009 12:04 12

166

Dveloppez des applications pour liPhone

prpares. Pour de plus amples informations concernant les instructions prpares, consultez la Section 2.
Tableau 7.3 : API de SQLTransaction

Attribut/mthode

Valeur de retour

Description

Paramtres

executeSQL(sqlStatement,
arguments, successCallback, errorCallback)

Aucune

Cette mthode excute


une chane dinstruction
SQL quelconque.

sqlStatement une
chane contenant une instruction SQL valide. Elle
peut inclure des points
dinterrogation (?) si elle
doit tre traite comme
une instruction prpare.

arguments un tableau
facultatif des valeurs utilises pour remplacer les
points dinterrogation (?)
dans les instructions prpares.
successCallback
une fonction facultative
qui est appele lorsque
lexcution de sqlStatement a russi.

errorCallback une
fonction facultative qui
est appele lorsque lexcution de sqlStatement
a chou.

Outre linstruction SQL, le paramtre facultatif arguments est pass. Il sagit dun tableau
de chanes de caractres qui vont remplacer les points dinterrogation inclus dans
linstruction SQL. Ils correspondent aux variables de linstruction prpare cre par
lappel executeSQL. Tous les appels executeSQL crent une instruction prpare,
mme lorsquil ny a aucun paramtre substituable. Son utilisation apporte donc plus de
sret, sans changer la rapidit de lapplication.
Les deux derniers paramtres dsignent les fonctions de rappel excutes lorsque
linstruction, non la transaction, russit ou choue. La fonction de succs reoit un objet
SQLResultSet de la part de la mthode executeSQL. Le Tableau 7.4 prsente lAPI de
SQLResultSet. La fonction dchec reoit un objet SQLError ; son API est dcrite au

iPhone Livre Page 167 Vendredi, 30. octobre 2009 12:04 12

Chapitre 7

Bases de donnes

167

Tableau 7.6. Pour traiter les rsultats de lexcution de linstruction SQL, vous devez
implmenter ces fonctions et les indiquer dans lappel la mthode executeSQL.
Lobjet SQLResultSet contient les informations que vous avez demandes au travers de
linstruction SQL. Il inclut galement deux lments intressants : les attributs insertID
et rowsAffected.
Lorsque la cl primaire dune table est incrmentation automatique et quun enregistrement est ajout cette table, lattribut insertID du SQLResultSet contient la valeur
gnre pour la cl. Ce fonctionnement est trs utile lorsque la cl est requise pour ajouter
des donnes associes dans dautres tables.
Aprs lexcution russie dune instruction SQL dinsertion ou de mise jour, lattribut
rowsAffected contient le nombre de lignes qui ont t ajoutes ou modifies. Cela permet
de valider le comportement des instructions SQL complexes.
Tableau 7.4 : API de SQLResultSet

Attribut/mthode

Valeur de retour

Description

Paramtres

insertID

Aucune

Un attribut entier en lec- Aucun


ture seule qui contient
lidentifiant de lenregistrement ajout si le
champ correspondant est
incrmentation automatique.

rowsAffected

Aucune

Un attribut entier en lec- Aucun


ture seule qui contient le
nombre de lignes ajoutes ou modifies par une
opration de type mise
jour.

rows

Aucune

Un attribut SQLResult- Aucun


SetRowList qui contient
toutes les lignes retournes par une instruction
de type requte.

Le troisime attribut de SQLResultSet se nomme rows. Il contient un SQLResultSetRowList, qui reprsente un tableau denregistrements. Le Tableau 7.5 montre que son attribut

iPhone Livre Page 168 Vendredi, 30. octobre 2009 12:04 12

168

Dveloppez des applications pour liPhone

length prcise le nombre denregistrements obtenus par une instruction de type SELECT. Il
correspond au nombre de lignes contenues dans le tableau.
Tableau 7.5 : API de SQLResultSetRowList

Attribut/mthode

Valeur de retour

Description

Paramtres

length

Aucune

Un attribut en lecture
seule qui contient le
nombre denregistrements obtenus par une
instruction de type
requte.

Aucun.

item(index)

Tableau

Une mthode qui


retourne un enregistrement sous forme de
tableau associatif ou de
mappe JavaScript.

index lindice de
lenregistrement dans le
jeu des rsultats retourner.

Il offre galement la mthode item pour accder chaque ligne des rsultats. Grce cette
mthode et lattribut, il est facile ditrer sur les lignes et leurs valeurs laide de boucles
for. Voici la solution gnralement employe pour effectuer ces itrations :
1 for( var i = 0; i < aResultSet.length; i++){
2
var aRow = aResultSet.item(i);
3
for(key in aRow){
4
var aValue = aRow[key];
5
// Exploiter la cl et la valeur.
6
}
7 }

Bien que le code prcdent puisse tre considr par beaucoup comme une solution standard, son excution nest pas optimale car, la ligne 1, la taille du jeu de rsultats est obtenue chaque tour de boucle externe. Un autre gaspillage est gnr par la rptition de la
boucle for-each la ligne 3.
Les boucles JavaScript for-each sont particulirement gourmandes en cycles processeur,
notamment lorsquelles sont employes dans dautres boucles. Plus loin dans cette section,
la description de la mthode dbAccess montrera comment optimiser ce code.
Si lexcution de linstruction SQL provoque une erreur, quelle quen soit la raison, un
objet SQLError est gnr la place de lobjet SQLResultSet. De mme quun SQLResultSet est pass la fonction de russite indique en argument de la mthode executeSQL,
un SQLError est pass la fonction dchec.

iPhone Livre Page 169 Vendredi, 30. octobre 2009 12:04 12

Chapitre 7

Bases de donnes

169

La fonction de succs ne reoit jamais un SQLError et la fonction derreur ne reoit jamais


un SQLResultSet. Ainsi, chacune de ces fonctions remplit un seul objectif et devient donc
plus facile crer, crire et maintenir.
Lobjet SQLError contient deux attributs qui correspondent un numro de code derreur
et un message derreur gnrs par SQLite (voir Tableau 7.6).
Tableau 7.6 : API de SQLError

Attribut/mthode

Valeur de retour

Description

Paramtres

code

Aucune

Un attribut en lecture seule qui contient le numro


du code de lerreur. Les codes possibles sont :

Aucun.

0 la transaction a chou pour une raison inconnue.


1 Linstruction a chou pour une raison inconnue.
2 Linstruction a chou car la version attendue de
la base de donnes ne correspond pas sa version
relle.
3 Linstruction a chou car le nombre de donnes
retournes tait trop important. Essayez dutiliser le
modificateur SQL LIMIT.
4 Linstruction a chou car les limites mmoire
ont t atteintes et lutilisateur na pas accept de les
augmenter.
5 Linstruction a chou en raison dun chec du
verrouillage dans la transaction.
6 Une instruction INSERT, UPDATE ou REPLACE a
chou car elle ne respecte pas une contrainte,
comme un cas de cl unique duplique.

message

Aucune

Un attribut en lecture seule qui contient un message Aucun.


derreur appropri.

code et message sont utiles aux programmeurs, mais ne doivent pas tre prsents aux
utilisateurs, car ils ne sauront pas ce quils reprsentent. Ces attributs doivent servir journaliser lerreur et afficher une information utile aux utilisateurs.
La mthode dbAccess de DataAccessObject les utilise. Nous lavons mentionn prcdemment dans cette section, cette mthode prend cinq arguments et ralise le travail des

iPhone Livre Page 170 Vendredi, 30. octobre 2009 12:04 12

170

Dveloppez des applications pour liPhone

mthodes de faade getData et setData. Son quatrime argument indique si la requte


modifie ou consulte la base de donnes. Sa valeur est fixe par la fonction de faade qui
invoque dbAccess.
En examinant la mthode dbAccess, vous constaterez quelle emploie plusieurs fonctions
anonymes. La premire est passe la ligne 3 en premier et seul paramtre de la mthode
transaction. Il pourrait sembler plus facile de la dfinir comme une fonction normale
ailleurs dans le code et de la passer en premier argument, mais, dans ce cas, le code restant
serait difficile, voire impossible, implmenter car des variables accessibles grce aux
fonctions anonymes ne le seraient alors plus. La ligne 2 du code suivant instancie lobjet
QueryResult, qui est utilis comme valeur de retour de la mthode dbAccess.
Pour quun objet QueryResult soit vritablement utile, il doit tre disponible depuis
lintrieur de la fonction executeSQL de la transaction. Sans les fonctions anonymes, la
seule manire de procder consiste le rendre global.
Sil est dclar de manire globale, un seul accs la base de donnes ne peut avoir lieu
la fois. Puisque tous les accs la base de donnes sont asynchrones, ce fonctionnement
est impossible garantir. Par consquent, la meilleure approche consiste opter pour des
fonctions anonymes. Cette mme logique sapplique aux fonctions passes la mthode
executeSQL de la transaction elle-mme.
La mthode executeSQL de lobjet Transaction peut recevoir deux fonctions en paramtres.
Les bonnes pratiques stipulent quelles doivent toujours tre passes. Le second paramtre
correspond la fonction qui traite les rsultats lorsque la requte se passe parfaitement (voir
Tableau 7.6). La dclaration de cette fonction commence la ligne 10 du code ci-aprs.
Dans la fonction de russite, tout identifiant gnr par linstruction SQL est enregistr
dans le QueryResult instanci la ligne 7. Si des lignes de la base de donnes sont modifies, leur nombre est galement indiqu, mais uniquement si le paramtre treatAsChangeData de la mthode dbAccess est fix true.
Si des donnes nont pas t modifies, une requte a d tre excute. Les lignes 23 51
prennent en charge ce cas. Dans ces lignes, un tableau JavaScript deux dimensions est
cr et associ au QueryResult. Toutes les valeurs qui se trouvent dans le jeu de rsultats
SQLResult y sont enregistres. En transfrant les donnes dans un tableau JavaScript standard, vous pouvez accder ces donnes dans un autre code, sans connatre la structure de
lobjet SQLResult ni les champs renvoys par la requte. Si vous souhaitez connatre les
noms des champs, ils sont galement prsents dans lobjet QueryResult. Les noms et les
valeurs des champs conservent lordre dans lequel ils se trouvent dans le SQLResult.
1
2
3

this.dbAccess = function(SQL, preparedStatementParameters,


treatAsChangeData, passThroughParameters){
if(!this.db){

iPhone Livre Page 171 Vendredi, 30. octobre 2009 12:04 12

Chapitre 7

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

Bases de donnes

171

this.db = openDatabase(dbName, dbVersion,


dbDescription, dbSize);
}
var queryResult = new QueryResult();
this.db.transaction(function(tx) {
tx.executeSql(SQL, preparedStatementParameters,
function(tx, resultSet) {
if(treatAsChangeData){
try{
queryResult.insertedID = resultSet.insertId;
queryResult.rowsAffected =
resultSet.rowsAffected;
}
catch(ex){
// Il doit sagir une mise jour.
queryResult.rowsAffected =
resultSet.rowsAffected;
}
}
else{
// La base de donnes na pas t modifie.
// Il doit sagir dune requte.
queryResult.numRowsFetched =
resultSet.rows.length;
var dataArray = new Array();
queryResult.numResultFields = 0;
queryResult.fieldNames = new Array();
if(queryResult.numRowsFetched > 0){
// Obtenir les identifiants des champs dans le jeu de rsultats.
firstRecord = resultSet.rows.item(0);
var numFields = 0;
for(key in firstRecord){
queryResult.fieldNames.push(key);
numFields++;
}
queryResult.numResultFields = numFields;
var numRecords =
queryResult.numRowsFetched;
for(var i = 0; i < numRecords; i++){
var record = resultSet.rows.item(i);
var row = new Array();
dataArray.push(row);
for(var j = 0; j < numFields; j++){
row.push(
record[queryResult.fieldNames[j]]);
}
}

iPhone Livre Page 172 Vendredi, 30. octobre 2009 12:04 12

172

Dveloppez des applications pour liPhone

51
}
52
queryResult.data = dataArray;
53
}
54
if(window.callFunc){
55
var theResults = new Array();
56
theResults.push(queryResult);
57
theResults.push(passThroughParameters);
58
requestHandler(passThroughParameters[0],
59
passThroughParameters[2], theResults);
60
}
61
}// Fin de la fonction de rappel en cas de succs de lexcution.
62
, function(tx, error) {
63
queryResult.errorMessage = error.message;
64
if(window.callFunc){
65
var theResults = new Array();
66
theResults.push(queryResult);
67
theResults.push(passThroughParameters);
68
requestHandler(passThroughParameters[0],
69
passThroughParameters[2], theResults);
70
}
71
}// Fin de la fonction de rappel en cas dchec de lexcution.
72
);// Fin de lappel principal executeSql.
73
});// Fin de la fonction de rappel de la transaction.
74 }// Fin de la mthode dbAccess.

Quel que soit le type de linstruction SQL excute, modification ou interrogation de la


base de donnes, lobjet QueryResult cr au dbut de la fonction est envoy par le
framework toutes les fonctions de contrle restantes non invoques. Cela se passe aux
lignes 58 et 59 laide de la fonction requestHandler dcrite au Chapitre 2.
La ligne 62 dbute la dclaration de la fonction de traitement des erreurs pour lobjet
Transaction. Cette fonction doit insrer le message derreur gnr par SQLite dans le
QueryResult et le transmettre aux fonctions de contrle restantes. Pour de plus amples
informations concernant les fonctions de contrle, consultez le Chapitre 2.

Section 5 : utilisation de DataAccessObject


avec les bases de donnes natives
Pour accder aux bases de donnes natives, il faut moins de code JavaScript que pour accder aux bases de donnes du moteur WebKit. Une grande partie du travail est effectue du
ct Objective-C du framework.

iPhone Livre Page 173 Vendredi, 30. octobre 2009 12:04 12

Chapitre 7

Bases de donnes

173

linstar de getData et de setData, les mthodes getNativeData et setNativeData


sont des faades. Toutefois, elles appellent non pas la mthode dbAccess de DataAccessObject, mais la fonction getDeviceData dfinie dans le fichier QCUtilities.js.
this.getNativeData =
function(SQL, preparedStatementParameters){
getDeviceData(dbName, SQL, preparedStatementParameters);
}
this.setNativeData =
function(SQL, preparedStatementParameters){
setDeviceData(dbName, SQL, preparedStatementParameters);
}

La fonction getDeviceData est constitue de deux parties. La premire, reprsente par


les lignes 4 16, construit un tableau des informations ncessaires lexcution de la
requte en Objective-C. Cela comprend notamment les paramtres gnraux dcrits la
section prcdente. Ces paramtres sont requis, car, comme dans le traitement des requtes
aux bases de donnes du moteur WebKit, la requte est asynchrone. Pour de plus amples
informations concernant les appels asynchrones, consultez le Chapitre 2.
Le tableau cr contient le nom de la base de donnes, linstruction SQL excuter, les
paramtres de linstruction SQL prpare et les paramtres gnraux. La section prcdente de ce chapitre a donn les explications concernant les instructions prpares.
1 function getDeviceData(dbName, SQL,
2
preparedStatementParameters, callBackParams){
3
if(dbName && SQL){
4
var dataArray = new Array();
5
dataArray.push(dbName);
6
dataArray.push(SQL);
7
if(preparedStatementParameters){
8
dataArray.push(preparedStatementParameters);
9
}
10
else{
11
// Placer un paramtre substituable.
12
dataArray.push(new Array());
13
}
14
var callBackParameters =
15
generatePassThroughParameters();
16
dataArray.push(callBackParameters);
17
18
var dataString = JSON.stringify(dataArray);
19
makeCall("getData", dataString);
20
}
21
return null;
22 }

iPhone Livre Page 174 Vendredi, 30. octobre 2009 12:04 12

174

Dveloppez des applications pour liPhone

Lorsque les donnes sont prtes, elles sont converties en une chane JSON passe la
fonction makeCall. Nous lavons vu au Chapitre 4, cette fonction active le ct ObjectiveC du framework. Il sagit l de la deuxime partie importante de la fonction getDeviceData. Sans elle, les bases de donnes natives seraient inaccessibles. Pour de plus amples
informations concernant JSON, consultez lAnnexe A.
linstar des fonctions du Chapitre 4 qui accdent aux donnes natives, des objets de
contrle Objective-C sont ncessaires lobtention des donnes depuis la base. Ces deux
objets, SetDataBCO et GetDataBCO, interagissent avec la base de donnes, quelle soit
modifie ou consulte. Ce fonctionnement est comparable celui des fonctions JavaScript
getData et setData.
+ (id) doCommand:(NSArray*) parameters{
if( [parameters count] >= 3){
NSString *dbName = [parameters objectAtIndex:1];
NSString *SQL = [parameters objectAtIndex:2];
NSArray *perparedStatementValues = nil;
if([parameters count] == 4){
perparedStatementValues = [parameters objectAtIndex:3];
}
SQLiteDataAccess *aDBAccess =
[SQLiteDataAccess getInstance:dbName isWriteable:YES];
return [aDBAccess getData:SQL withParameters:perparedStatementValues];
}
return nil;
}
@end

Par ailleurs, comme les fonctions JavaScript getData et setData, le code de traitement
dans ces BCO est court. La commande doCommand permet dobtenir le nom de la base de
donnes, linstruction SQL et les paramtres de linstruction prpare provenant de la
requte JavaScript.
Lorsque tous ces lments dinformations sont disponibles, la mthode getData de lobjet
SQLiteDataAccess est invoque. Cet objet est essentiellement un clone de lobjet JavaScript DataAccessObject. Il offre les mthodes getData et setData, mais, contrairement
la version JavaScript, la version Objective-C est un singleton. Pour de plus amples informations concernant les singletons, consultez le Chapitre 4.
Les mthodes getData et setData de SQLiteDataAccess sont des faades pour la
mthode dbAccess. De mme que la mthode JavaScript dbAccess, la version ObjectiveC est particulirement complexe. Cela provient de la complexit de lAPI SQLite dfinie

iPhone Livre Page 175 Vendredi, 30. octobre 2009 12:04 12

Chapitre 7

Bases de donnes

175

par la bibliothque dynamique libsqlite3.0.dylib fournie avec chaque iPhone et iPod Touch
(voir Tableau 7.7).
Tableau 7.7 : API de SQLite3

Objet/fonction

Valeur de retour

Description

Paramtres

sqlite3

Aucune

Un objet qui reprsente


la base de donnes
SQLite en mmoire.

Aucun.

Ouvre le fichier de base


de donnes indiqu par
filePath et enregistre
le pointeur dans
aDatabase.

filePath le chemin

sqlite3_open
int SQLITE_OK
(filePath, &aDatabase) en cas de succs
de louverture

complet du fichier de base


de donnes SQLite sur la
machine.

aDatabase une rfrence


vers un pointeur SQLite3
qui reprsente la base de
donnes en mmoire.
sqlite3_close
(aDatabase)

void

Ferme les connexions


au fichier de base de
donnes SQLite.

aDatabase un pointeur
SQLite3 fix dans la fonction sqlite3_open.

sqlite3_errmsg
(aDatabase)

const char *

Obtient la dernire
erreur gnre.

aDatabase un pointeur
SQLite3 vers la base de
donnes dont on souhaite
obtenir un message
derreur.

sqlite3_stmt

Aucune

Une seule instruction


SQL prpare.

Aucun.

sqlite3_prepare_v2
(aDatabase, SQLChar,
-1, &statement, NULL)

int SQLite_OK
en cas de succs

Interprte linstruction
SQL.

aDatabase un pointeur
SQLite3 vers la base de
donnes.

SQLChar une chane


const char * de caractres UTF8 qui reprsente
linstruction SQL.

sqlite3_column_count
(statement)

int

Compte le nombre
de champs dans le jeu
de rsultats dune
requte.

statement un pointeur
sqlite3_stmt.

iPhone Livre Page 176 Vendredi, 30. octobre 2009 12:04 12

176

Dveloppez des applications pour liPhone

Tableau 7.7 : API de SQLite3 (suite)

Objet/fonction

Valeur de retour

Description

Paramtres

sqlite3_column_name
(statement, i)

const char *

Obtient le nom dun


champ.

statement un pointeur
sqlite3_stmt.
i un entier qui
reprsente le numro du
champ.

sqlite3_changes
(database)

sqlite3_step
(statement)

sqlite3_column_type
(statement, i)

int

int SQLITE_ROW
lorsquune ligne
est disponible

int
Valeurs
possibles:

Obtient le nombre
denregistrements
affects par la modification dune table.

aDatabase un pointeur
SQLite3 vers la base de
donnes.

Dplace le curseur vers


lenregistrement suivant dans le jeu de
rsultats.

statement un pointeur
sqlite3_stmt.

Obtient le type dun


champ (colonne)
dans le jeu de rsultats
dune instruction.

statement un pointeur
sqlite3_stmt.
i le numro du champ
dont on souhaite obtenir
les donnes.

SQLITE_INTEGER
SQLITE_FLOAT
SQLITE_BLOB
SQLITE_NULL
SQLITE_TEXT
sqlite3_column_int
(statement, i)

int

Obtient la valeur dun


champ de type entier.

statement un pointeur
sqlite3_stmt.
i le numro du champ
dont on souhaite obtenir
les donnes.

sqlite3_column_double
(statement, i)

double

Obtient la valeur dun


champ de type rel.

statement un pointeur
sqlite3_stmt.
i le numro du champ
dont on souhaite obtenir
les donnes.

iPhone Livre Page 177 Vendredi, 30. octobre 2009 12:04 12

Chapitre 7

Bases de donnes

177

Tableau 7.7 : API de SQLite3 (suite)

Objet/fonction

Valeur de retour

Description

Paramtres

sqlite3_column_text
(statement, i)

const unsigned
char *

Obtient la valeur dun


champ de type chane
de caractres.

statement un pointeur
sqlite3_stmt.
i le numro du champ
dont on souhaite obtenir
les donnes.

sqlite3_column_blob
(statement, i)

byte *

Obtient les octets dun


champ de type BLOB
(binary large object).

statement un pointeur
sqlite3_stmt.
i le numro du champ
dont on souhaite obtenir
les donnes.

sqlite3_column_bytes
(statement, i)

int

Obtient le nombre
doctets de la valeur dun
champ de type BLOB.

statement un pointeur
sqlite3_stmt.
i le numro du champ dont
on souhaite obtenir les
donnes.

sqlite3_finalize
(statement)

void

sqlite3_bind_blob
int
(statement, parameterIndex, aVariable, byteLength, transienceKey)

libre les ressources


associes linstruction.

statement un pointeur
sqlite3_stmt.

Lie un pointeur sur un


tableau doctets un
paramtre substituable
dune instruction prpare.

statement un pointeur
sqlite3_stmt.
parameterIndex
lindice du paramtre
substituable dans
linstruction prpare.

aVariable un pointeur sur


le tableau doctets
enregistrer dans la base de
donnes.
byteLength le nombre
doctets enregistrer.

transienceKey un
indicateur prcisant si les
donnes insres doivent
tre copies avant
linsertion afin dviter
leur modification pendant
lenregistrement.

iPhone Livre Page 178 Vendredi, 30. octobre 2009 12:04 12

178

Dveloppez des applications pour liPhone

Tableau 7.7 : API de SQLite3 (suite)

Objet/fonction

Valeur de retour

sqlite3_bind_double
int
(statement, parameterIndex, aVariable)

Description

Paramtres

Lie une valeur relle


un paramtre substituable dune
instructionprpare.

statement un pointeur
sqlite3_stmt.
parameterIndex
lindice du paramtre
substituable dans
linstruction prpare.

aVariable un nombre
rel enregistrer dans la
base de donnes.
sqlite3_bind_int
int
(statement, parameterIndex, aVariable)

Lie une valeur entire


un paramtre substituable dune instruction
prpare.

statement un pointeur
sqlite3_stmt.
parameterIndex
lindice du paramtre
substituable dans
linstruction prpare.

aVariable un nombre
entier enregistrer dans la
base de donnes.

Cette bibliothque C contient toutes les fonctions utilises pour laccs aux bases de
donnes SQLite. Elle prend galement en charge les transactions et les instructions prpares. Le code ci-aprs montre comment employer cette API avec les instructions prpares. Il provient de la mthode dbAccess de lobjet SQLiteDataAccess. Comme le stipule
lAPI, la fonction sqlite3_prepare_v2 attend des pointeurs sur la base de donnes, sur
linstruction SQL excuter et sur un pointeur vers une variable sqlite3_stmt. En cas
derreur au cours de lexcution de linstruction SQL, sqlite3_prepare_v2 retourne un
code numrique qui reprsente lerreur.
int numResultColumns = 0;
sqlite3_stmt *statement = nil;
const char* SQLChar = [SQL UTF8String];
if (sqlite3_prepare_v2(database, SQLChar, -1,
&statement, NULL) == SQLITE_OK) {
...
}

iPhone Livre Page 179 Vendredi, 30. octobre 2009 12:04 12

Chapitre 7

Bases de donnes

179

Dans le code prcdent, la variable sqlite3_stmt passe a t fixe au cours de lexcution de


la fonction sqlite3_prepare_v2 et contient le sqlite3_stmt qui est ensuite utilis pour
obtenir chaque lment de donnes du jeu de rsultats de la requte SQL excute. Une
suite dappels la fonction sqlite3_step dplace un curseur qui dsigne la position de la
ligne dans le jeu des rsultats. Ainsi, lorsque le jeu de rsultats est vide, ou ne contient
aucune ligne, sqlite3_step retourne non plus SQLITE_ROW mais SQLITE_DONE. Cela
permet dutiliser une instruction while pour extraire les donnes de la ligne indique par
le curseur.
while (sqlite3_step(statement) == SQLITE_ROW) {
...
}

Dans cette boucle while, plusieurs NSMutableArrays sont crs ; voir la ligne 218 du
fichier SQLiteDataAccess.m et la ligne suivante. Chacun de ces tableaux reprsente une
ligne du jeu de rsultats et se nomme donc row.
NSMutableArray *row = [[NSMutableArray alloc] initWithCapacity:numResultColumns];

Pour obtenir les valeurs des diffrents champs des enregistrements du jeu de rsultats, il
faut appeler les fonctions associes au type appropri. Le Tableau 7.7 recense ces fonctions et
le code suivant montre comment les utiliser.
int type = [[[theResult columnTypes]
objectAtIndex:i] intValue];
if(type == SQLITE_INTEGER){
NSNumber *aNum = [[NSNumber alloc]
initWithInt: sqlite3_column_int(statement, i)];
[row addObject:aNum];
[aNum autorelease];
}
else if(type == SQLITE_FLOAT){
NSNumber *aFloat = [[NSNumber alloc]
initWithFloat:sqlite3_column_double(statement, i)];
[row addObject:aFloat];
[aFloat autorelease];
}
else if(type == SQLITE_TEXT){
NSString *aText = [[NSString alloc]
initWithCString:sqlite3_column_text(statement, i)
encoding:NSASCIIStringEncoding];
[row addObject:aText];
[aText autorelease];
}
else if(type == SQLITE_BLOB){

iPhone Livre Page 180 Vendredi, 30. octobre 2009 12:04 12

180

Dveloppez des applications pour liPhone

NSData *aData = [[NSData alloc]


dataWithBytes:sqlite3_column_blob(statement, i)
length:sqlite3_column_bytes(statement,i)];
[row addObject:aData];
[aData autorelease];
}
else{//SQLITE_NULL
[row addObject:@"null"];
}

Pour appeler la fonction approprie, le type du champ concern doit tre dtermin. Pour
cela, le type du champ est examin et enregistr avant lappel ; voir les lignes 199 205
dans le fichier SQLiteDataAccess.m et le code suivant.
NSMutableArray *columnTypes = [[NSMutableArray alloc]
initWithCapacity:0];
for(int i = 0; i < numResultColumns; i++){
NSNumber * columnType = [NSNumber numberWithInt:
sqlite3_column_type(statement,i)];
[columnTypes addObject:columnType];
}
[theResult setColumnTypes:columnTypes];

Le type de chaque colonne est obtenu partir du jeu de rsultats de linstruction en invoquant la fonction sqlite3_column_type. Le pointeur sur linstruction et le numro du
champ concern sont passs la fonction, qui retourne un indicateur numrique du type de
ce champ. Voici les types reconnus :

SQLITE_INTEGER ;

SQLITE_FLOAT ;

SQLITE_BLOB ;

SQLITE_NULL ;

SQLITE_TEXT.

Les mthodes dbAccess, setData et getData retournent un pointeur sur un DataAccessResult. Cet objet contient les rsultats de lexcution dune instruction SQL sur une base
de donnes SQLite. Le code suivant est extrait du fichier DataAccessResult.h et montre les
champs utiliss pour enregistrer les rsultats dune excution SQL.
@interface DataAccessResult: NSObject {
NSArray *fieldNames;
NSArray *columnTypes;
NSArray *results;

iPhone Livre Page 181 Vendredi, 30. octobre 2009 12:04 12

Chapitre 7

Bases de donnes

181

NSString *errorDescription;
NSInteger rowsAffected;
NSInteger insertedID;
}
@property
@property
@property
@property
@property
@property

(nonatomic,
(nonatomic,
(nonatomic,
(nonatomic,
(nonatomic)
(nonatomic)

retain) NSArray *fieldNames;


retain) NSArray *columnTypes;
retain) NSArray *results;
retain) NSString *errorDescription;
NSInteger rowsAffected;
NSInteger insertedID;

- (NSString*) JSONStringify;
@end

Le Chapitre 4 la expliqu, puisque le framework prend en charge le passage des donnes,


tous les objets DataAccessResult gnrs par des appels SQLiteDataAccess sont
inclus dans les paramtres transmis aux objets de contrle de laffichage (VCO, View
Control Object). Puisquun appel JavaScript est effectu pour obtenir ou fixer les donnes
dans une base de donnes "native", les rsultats de la requte doivent tre renvoys
lapplication JavaScript. Cette opration est ralise par lobjet SendDBResultVCO.
linstar de tous les objets de commande, SendDBResultVCO offre une mthode doCommand. Puisque les donnes doivent tre renvoyes au code JavaScript, elles sont converties
en une chane JSON (lignes 8 11 du code suivant). Chaque rsultat est dabord converti
en une chane JSON et ajout au tableau retVal de type NSMutableArray. Ce tableau est
ensuite converti en une chane JSON. En raison des limitations de la bibliothque JSON
dObjective-C, il est impossible de convertir les tableaux dobjets en une chane JSON en
un seul appel. La bibliothque ne parcourt pas les objets des tableaux pour effectuer les
conversions appropries. Un appel supplmentaire JSONStringify est donc ncessaire
pour chaque objet DataAccessResult.
1
2
3
4
5
6
7
8

+ (id) doCommand:(NSArray*) parameters{


...
NSArray *results = [parameters subarrayWithRange:aRange];
int numResults = [results count];
NSMutableArray *retVal = [[NSMutableArray alloc] init];
for(int i = 0; i < numResults; i++){
DataAccessResult * aResult =
(DataAccessResult*)[results objectAtIndex:i];
NSString* resultString = [aResult JSONStringify];

iPhone Livre Page 182 Vendredi, 30. octobre 2009 12:04 12

182

Dveloppez des applications pour liPhone

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

[retVal addObject:resultString];
}
[retVal addObject:[parameters objectAtIndex:4]];
SBJSON *generator = [SBJSON alloc];
NSError *error;
NSString *dataString = [generator stringWithObject:retVal error:&error];
[generator release];
dataString = [dataString
stringByReplacingOccurrencesOfString:@"" withString:@"\\"];
NSString *jsString = [[NSString alloc]
initWithFormat:
@"handleRequestCompletionFromNative(%@)
, dataString];
QuickConnectViewController *controller =
[parameters objectAtIndex:0];
[controller.webView
stringByEvaluatingJavaScriptFromString:jsString]);
return nil;

Comme au Chapitre 4, o les rsultats taient convertis en une chane JSON, un appel
permet de les passer la partie JavaScript de lapplication en vue de leur traitement. Il sagit
de lappel stringByEvaluatingJavaScriptFromString vu prcdemment. Il excute la
fonction JavaScript handleRequestCompletionFromNative pour sassurer que tous les
autres BCO et VCO associs la commande dorigine soient excuts. Pour de plus
amples informations concernant ce fonctionnement, consultez le Chapitre 5.

En rsum
Le module JavaScript DataAccessObject facilite normment les interactions avec les
bases de donnes SQLite prises en charge par le moteur WebKit. Puisque ce module
accepte uniquement les types JavaScript standard, comme les chanes de caractres et les
tableaux, il est plus facile employer que les fonctions JavaScript SQLite de WebKit.
DataAccessObject est galement une faade utilise pour accder aux fichiers de base de
donnes "natives" que vous pouvez livrer avec votre application. Avec des appels JavaScript, il est possible daccder aux donnes prsentes dans la base. De cette manire,
lapplication JavaScript est une application complte qui offre les mmes fonctionnalits
que lapplication quivalente crite en Objective-C.
linstar du DataAccessObject JavaScript, la classe Objective-C SQLiteDataAccess
facilite lextraction ou lenregistrement des donnes dans des bases SQLite livres avec

iPhone Livre Page 183 Vendredi, 30. octobre 2009 12:04 12

Chapitre 7

Bases de donnes

183

lapplication. Puisquelle suit la mme conception que la classe JavaScript DataAccessObject, il est plus facile de comprendre son rle, mme sans matriser Objective-C.
Puisque tous les rsultats des requtes effectues sur les bases de donnes du moteur
WebKit ou les bases de donnes "natives" sont des objets qui contiennent des types JavaScript standard, il est inutile de connatre les dtails internes du fonctionnement de SQLite
avec WebKit ou en natif.
DataAccessObject et SQLiteDataAccess se fondent sur les transactions pour viter que
les appels asynchrones ne perturbent les requtes. Vous pouvez effectuer plusieurs appels
concurrents la base de donnes sans vous inquiter dventuelles perturbations sur les
donnes dans la base. Le chapitre suivant explique comment raliser une enveloppe pour les
appels AJAX qui ressemble et se comporte de manire comparable DataAccessObject.

iPhone Livre Page 184 Vendredi, 30. octobre 2009 12:04 12

iPhone Livre Page 185 Vendredi, 30. octobre 2009 12:04 12

8
Donnes distantes
Votre application peut avoir besoin daccder des donnes qui se trouvent dans une base
de donnes distante ou qui sont fournies par des services web. Vous pourriez mme vouloir
synchroniser les donnes du tlphone avec des donnes enregistres distance.
Les applications hybrides pour liPhone facilitent la mise en uvre de ces comportements.
Puisquelles sont hybrides, elles disposent dun accs total lobjet XMLHttpRequest
depuis le code JavaScript. Ce chapitre explique comment obtenir des donnes partir dun
flux RSS et les afficher dans votre application.
Comme pour laccs aux bases de donnes examin au Chapitre 7, une enveloppe
simple demploi pour lobjet XMLHttpRequest est dcrite dans la premire section. Les
sections suivantes expliquent comment cette enveloppe a t cre et son fonctionnement interne.

iPhone Livre Page 186 Vendredi, 30. octobre 2009 12:04 12

186

Dveloppez des applications pour liPhone

Section 1 : application browserAJAXAccess


Au Chapitre 7, lapplication nativeDBAccess a illustr lenregistrement et la rcupration
des donnes partir dune base de donnes SQLite sur un appareil. Ce chapitre dcrit une
application semblable qui permet dinteragir avec des services et des serveurs web pour
obtenir des donnes. La Figure 8.1 montre lapplication browserAJAXAccess en cours
dexcution.
Figure 8.1
Lapplication
browserAJAXAccess
affiche le contenu du blog
de TetonTech.

Tous les blogs WordPress proposent un flux RSS qui fournit les dix derniers billets du blog
(voir Figure 8.2). Bien que ce flux ne semble pas proposer lensemble des billets du blog, en
ralit ce nest pas le cas. Lapplication browserAJAXAccess affiche uniquement les intituls, mais il est trs facile de ltendre pour enregistrer les intituls et les billets la
manire dcrite au Chapitre 7.
Heureusement, les flux RSS se moquent du client. Un flux reoit une demande pour les
billets du blog et les envoie au format XML, quel que soit le demandeur. Puisque UIWebView intgre le moteur WebKit, il peut envoyer des requtes au flux et interprter le
contenu XML reu. Pour cela, loutil utilis prend la forme de lobjet XMLHttpRequest et
la mthode employe se nomme AJAX.

iPhone Livre Page 187 Vendredi, 30. octobre 2009 12:04 12

Chapitre 8

Donnes distantes

187

Figure 8.2
Le flux RSS de TetonTech
affich dans Safari.

AJAX na rien de grec


LIliade est lun des plus grands textes de tous les temps. Cette pope dHomre raconte
la guerre entres les Grecs, ou Achens, et les Troyens.
Lun des hros grecs se nomme Ajax. Il bat constamment ses adversaires et, lors dun
pisode, il sauve lui seul la flotte grecque de la destruction.
linstar de la flotte grecque, le dveloppement traditionnel des pages web a subi et
subit des attaques. On lui reproche dtre trop lent, trop difficile employer et pas assez
flexible. Une fois encore, AJAX vient la rescousse, mais il ne sagit plus du hros grec. Ce
nouvel AJAX signifie Asynchronous JavaScript and XML.
Lide derrire AJAX est simple : amliorer lexprience utilisateur en ne rechargeant pas
les pages chaque requte. la place, des donnes sont envoyes ou obtenues, et les
rsultats sont prsents en employant des techniques issues du HTML dynamique. Tout
cela peut tre ralis dans une page laide de JavaScript.

En conjuguant lobjet XMLHttpRequest et du code JavaScript simple pour manipuler une


page web, votre application hybride pour liPhone peut exploiter des donnes distantes
comme si elles taient locales. Vous obtenez alors le meilleur des deux mondes : lapplication

iPhone Livre Page 188 Vendredi, 30. octobre 2009 12:04 12

188

Dveloppez des applications pour liPhone

peut sexcuter en mode autonome, sexcuter en mode rseau et synchroniser les donnes
lorsquune connexion est disponible. Le framework QuickConnectiPhone fournit une
enveloppe AJAX simple demploi : ServerAccessObject.

Section 2 : utilisation de ServerAccessObject


Lenveloppe AJAX ServerAccessObject vous permet daccder facilement des
donnes distantes sans connatre les dtails de lAPI de XMLHttpRequest. LAPI de
ServerAccessObject est quasiment identique celle de DataAccessObject examine au
Chapitre 7. Elle comprend un constructeur et deux mthodes. Le constructeur enregistre
lURL du serveur distant et configure les mthodes de lobjet. Les deux mthodes,
getData et setData, permettent ensuite dobtenir et denvoyer des donnes au serveur
distant dfini dans le constructeur. Le Tableau 8.1 dcrit lAPI de ServerAccessObject.
Tableau 8.1 : API de ServerAccessObject

Attribut/mthode

Valeur de retour

Description

Paramtres

ServerAccessObject
(URL)

ServerAccesObject

Cre un ServerAccessObject lorsquelle est


appele avec le mot cl
new.

URL lURL du serveur


contacter.

Cette mthode permet


dobtenir des informations
depuis un serveur distant.
La requte est de type GET.
Cette mthode est sre vis-vis des threads.

dataType le type des


donnes obtenir : ServerAccessObject.XML ou
ServerAccessObject.TEXT.

getData(dataType,
void
refresh, parameterSequence, HTTPHeaders)

refresh un boolen qui


indique si une mise jour
force des donnes depuis le
serveur doit tre effectue.
parameterSequence les
paramtres ajouter
lURL. Le point dinterrogation initial (?) nest pas
inclus.

HTTPHeaders un tableau
associatif contenant les
noms et les valeurs des enttes envoyer avec la
requte.

iPhone Livre Page 189 Vendredi, 30. octobre 2009 12:04 12

Chapitre 8

Donnes distantes

189

Tableau 8.1 : API de ServerAccessObject (suite)

Attribut/mthode

Valeur de retour

Description

Paramtres

setData(dataType,
parameterSequence,
data, HTTPHeaders)

void

Cette mthode est utilise


pour modifier ou crer des
informations sur un serveur
distant, ou pour passer des
types de paramtres scuriss. La requte est de type
POST. Cette mthode est
sre vis--vis des threads.

dataType le type des


donnes obtenir : ServerAccessObject.XML ou
ServerAccessObject.TEXT.
parameterSequence les
paramtres ajouter
lURL. Le point dinterrogation initial (?) nest pas
inclus.

data les donnes


inclure dans lenvoi. Il peut
sagir dune grande quantit
de caractres, dun fichier,
etc.

HTTPHeaders un tableau
associatif contenant les
noms et les valeurs des enttes envoyer avec la
requte.

Le fichier ServerAccessObject.js, qui se trouve dans le groupe QCiPhone des modles


Dashcode et Xcode, contient lenveloppe ServerAccessObject. Il est automatiquement
inclus dans le fichier index.html de lapplication par les deux modles.
La fonction getSiteDataBCF, dfinie dans le fichier functions.js, utilise ServerAccessObject. Ce fichier JavaScript contient toutes les fonctions de contrle pour lapplication
browserAJAXAccess. Pour de plus amples informations concernant ces types de fonctions
et la manire de les crer, consultez le Chapitre 2.
Lobjectif de la fonction getSiteDataBCF est dobtenir les billets partir du blog de
lauteur. Ce comportement est facile mettre en uvre laide de lobjet ServerAccessObject, comme le montrent les lignes 2 5 du code suivant :
1 function getSiteDataBCF(parameters){
2
var site = new ServerAccessObject(
3
http://tetontech.wordpress.com/feed/);
4
site.getData(ServerAccessObject.XML,

iPhone Livre Page 190 Vendredi, 30. octobre 2009 12:04 12

190

Dveloppez des applications pour liPhone

ServerAccessObject.REFRESH);

// Puisque les appels AJAX sont asynchrones,

// cette BCF ne retourne aucune valeur.

8
9 }

Les lignes 2 et 3 construisent le ServerAccessObject. Il reoit lURL du flux RSS, dans


ce cas celle du blog de lauteur (http://tetontech.wordpress.com/feed). Pour accder un
autre blog WordPress, vous devez simplement remplacer cette URL.
Les lignes 4 et 5 utilisent ensuite ce nouvel objet nomm site pour obtenir les donnes.
Puisquil sagit dun flux RSS et que le serveur renvoie des donnes XML lapplication
browserAJAXAccess, on indique que les donnes sont de type XML. Le second paramtre
force une actualisation des donnes, au lieu quelles soient prises dans un cache. Ce fonctionnement est indispensable si vous souhaitez garantir que les donnes reues contiennent
toutes les modifications enregistres sur le serveur.
Une utilisation inconsidre de lactualisation peut conduire des effets secondaires ngatifs. Si lactualisation est demande alors quelle nest pas requise, le serveur et le rseau
peuvent se trouver surchargs dans le cas o lapplication devient populaire. Cest pourquoi il faut dterminer si les toutes dernires donnes doivent tre obtenues ou si elles
peuvent tre lgrement obsoltes.
linstar de DataAccessObject, tous les appels ServerAccessObject sont asynchrones.
Plusieurs appels peuvent tre effectus en parallle, tant quun nouveau Server-AccessObject est cr pour chacun deux. Avec le framework QuickConnectiPhone, il est inutile
de dfinir une fonction de rappel comme cela est requis lorsquon utilise AJAX. Le
framework sassure de lexcution des fonctions de contrle mtier (BCF, Business
Control Function) et des fonctions de contrle de laffichage (VCF, View Control Function)
associes la mme commande que la BCF qui invoque ServerAccessObject.
Dans le fichier mappings.js, les fonctions getSiteDataBCF et displaySiteDataVCF sont
associes la commande sampleQuery (voir Chapitre 2). Autrement dit, les donnes
demandes par getSiteDataBCF sont certaines dtre passes displaySiteDataVCF par
le framework.
Le code de displaySiteDataVCF est donn ci-aprs. Le paramtre results pass cette
fonction est un tableau dobjets JavaScript, un pour chaque BCF associe la commande
sampleQuery. La mthode getData de ServerAccessObject conduit la cration dun
objet QueryResult, comme ctait le cas dans la mthode getData de DataAccessObject ; pour de plus amples informations concernant lobjet QueryResult, consultez le
Chapitre 7.

iPhone Livre Page 191 Vendredi, 30. octobre 2009 12:04 12

Chapitre 8

Donnes distantes

191

Aprs avoir effac les lments affichs et reprsents par la variable container dans le
code suivant, lobjet QueryResult contenant les rsultats de lappel AJAX est obtenu
(ligne 9). Puisque getSiteDataBCF est la premire BCF associe la commande sampleQuery, les rsultats gnrs par son invocation se trouvent dans le premier objet du tableau
results pass en paramtre.
Nous lavons vu au Chapitre 7, les objets QueryResult possdent un attribut nomm
data. Dans le cas des requtes XML, comme celle effectue dans getSiteDataBCF, cet
attribut contient le document XML rsultant.
Puisque ce document est comparable un document utilis habituellement avec du
contenu HTML dynamique, il est trait de manire semblable. Les mmes types de mthodes sont disponibles, comme getElementById et getElementsByTagName. Il est galement constitu dobjets Node, avec des relations de parent, denfants et de frres. Vous
pouvez employer toutes les mthodes et solutions classiques pour interprter les donnes.
La fonction utilitaire parseWordPressFeed, dfinie dans le fichier RSSUtilities.js, est
appele la ligne 9. Elle emploie la mthode standard pour obtenir un tableau en deux
dimensions, nomm entries, qui contient les billets de blog. Chaque entre du tableau
comprend la date de publication, le contenu et lintitul du billet.
1 function displaySiteDataVCF(results, parameters){
2
var container =
3
document.getElementById(queryResults);
4
// Effacer le conteneur.
5
while(container.lastChild){
6
container.removeChild(container.lastChild);
7
}
8
// Utiliser un parseur wordpress pour crer les objets des billets.
9
var entries = parseWordPressFeed(results[0].data);
10
var numEntries = entries.length;
11
// Pour chaque billet, ajouter lintitul et la date
12
// dans le <div> conteneur.
13
for (var i = numEntries-1; i >= 0; i--){
14
var entry = entries[i];
15
var publishDate = entry.date;
16
var title = entry.title;
17
18
var titleElement = document.createElement(h2);
19
titleElement.innerText = entry.title;
20
container.appendChild(titleElement);
21
22
var dateElement = document.createElement(h3);

iPhone Livre Page 192 Vendredi, 30. octobre 2009 12:04 12

192

Dveloppez des applications pour liPhone

23
24
25
26
27
28
29 }

dateElement.innerText = entry.date;
container.appendChild(dateElement);
var hardRule = document.createElement(hr);
container.appendChild(hardRule);
}

Pour chaque entre gnre par la fonction parseWordPressFeed, les lignes 13 28


crent des objets HTML Element et les insrent dans le conteneur. Lintitul et la date de
chaque billet de blog sont ainsi affichs. Une ligne est ensuite ajoute pour sparer chaque
billet affich.
Cet exemple montre comment grer les flux RSS, mais dautres types daccs sont aussi
simples, si ce nest faciles. Vous pouvez effectuer une requte de type TEXT et obtenir le
contenu HTML insrer dans linterface utilisateur de votre application. Toutefois, cette
approche est dconseille pour des questions de scurit. Vous pouvez galement effectuer
un appel de type TEXT pour obtenir des donnes au format JSON.

JSON na rien de grec, lui non plus


JSON se prononce "Jaison", comme le Jason (avec laccent anglais) avec ses Argonautes.
Il est intressant de remarquer que le long voyage de Jason et de ses compagnons avait
pour objectif de ramener la Toison dor.
JSON (JavaScript Object Notation) est utilis pour faire voyager les objets JavaScript sur de
longues distances dans les rseaux. Le code suivant montre comment crer un objet JavaScript qui enregistre un nom et un prnom :
var unObjet = new Object();
unObjet.prenom = Paul;
unObjet.nom = Martin;

Le code suivant illustre une autre syntaxe :


var unObjet = {prenom:Paul, nom:Martin};

Lequel est correct ? Les deux ralisent la mme chose. La seconde solution est probablement plus rapide, mais, lorsque les objets sont grands, la premire est plus lisible et facile
modifier.
La seconde syntaxe a pour avantage de pouvoir tre passe sous forme dune chane de
caractres :
"{prenom:Paul, nom:Martin}"

iPhone Livre Page 193 Vendredi, 30. octobre 2009 12:04 12

Chapitre 8

Donnes distantes

193

Cette chane peut ensuite tre convertie en un objet en la passant la fonction JavaScript
standard eval, mais cette mthode est dangereuse. Pour une solution plus sre et simple
demploi, consultez lAnnexe A.
Est-ce une concidence si, tels les deux hros grecs, AJAX et JSON sont l pour sauver le
dveloppement de type web ? vous de dcider.

Quel que soit le type des donnes obtenir, ServerAccessObject facilite cette opration.
Il suffit simplement dinstancier cet objet et dappeler getData, pour une requte de type
GET, ou setData, pour une requte de type POST. Dans tous les cas, le framework QuickConnectiPhone passe les informations aux autres objets de contrle associs la
commande.

Section 3 : ServerAccessObject
La section prcdente a montr comment lutilisation de ServerAccessObject permettait
dexploiter les possibilits dAJAX et de lAPI de XMLHttpRequest sans avoir besoin de
matriser ces derniers. Cette section sintresse ces deux aspects et montre comment les
utiliser. Si vous souhaitez simplement vous servir de ServerAccessObject sans en
comprendre le fonctionnement, vous pouvez sauter cette section.
Grce ServerAccessObject, dfini dans le fichier ServerAccessObject.js du groupe
QCiPhone, le programmeur na pas besoin dune grande connaissance dAJAX pour en
exploiter les possibilits. Cette classe propose des mthodes et des constructeurs semblables ceux de lenveloppe JavaScript DataAccessObject dcrite au Chapitre 7. Puisquil
dispose dune API simplifie, le programmeur qui nest pas familier dAJAX peut envoyer
et obtenir des donnes distantes sans passer par une longue phase dapprentissage. Si vous
connaissez lAPI de lun de ces objets daccs, vous pouvez employer lautre.
Le constructeur de ServerAccessObject est la plus simple de ses mthodes. Il enregistre
lURL du serveur distant et dfinit ensuite les mthodes de lobjet. La ligne suivante,
extraite du constructeur, montre que lURL est enregistre dans lattribut URL de lobjet en
vue dune utilisation ultrieure.
this.URL = URL;

Outre cet attribut URL, auquel le programmeur naccde jamais directement, il faut galement
prendre en compte la mthode prive makeCall.
makeCall est au cur de ServerAccessObject. Elle effectue tout le travail requis par les
accs au serveur. Elle est invoque par les deux mthodes de faade getData et setData.
Le Tableau 8.2 dcrit son API et son utilisation de base.

iPhone Livre Page 194 Vendredi, 30. octobre 2009 12:04 12

194

Dveloppez des applications pour liPhone

Comme vous le verrez par la suite, lune des nombreuses solutions standard pour affecter
des mthodes des objets est employe pour ces faades. Elle consiste crer un objet de
fonction laide du constructeur function et affecter le rsultat un attribut de lobjet
courant reprsent par le mot cl this.
Les deux mthodes de faade getData et setData sont quasiment identiques. Elles prennent quatre arguments et les passent, ainsi que trois autres, la mthode makeCall. Les
paramtres supplmentaires sont le premier, le cinquime et le septime dans lappel
getData et le premier, le troisime et le septime dans lappel setData. Le cinquime
paramtre de la mthode makeCall prcise les donnes qui doivent tre passes au serveur
laide dune requte de type POST. Il est videmment inutile pour la mthode getData et
est donc remplac par null.
this.getData = function(dataType, refresh,
parameterSequence, HTTPHeaders){
var passThroughParameters = generatePassThroughParameters();
this.makeCall(GET, dataType, refresh,
parameterSequence, null, HTTPHeaders, passThroughParameters);
}
this.setData = function(dataType,
parameterSequence, data, HTTPHeaders){
var passThroughParameters = generatePassThroughParameters();
this.makeCall(POST, dataType, true,
parameterSequence, data, HTTPHeaders, passThroughParameters);
}

Lappel la fonction generatePassThroughParameters assemble toutes les informations


qui permettent au framework de poursuivre le traitement des BCF et VCF associes la
BCF en utilisant ServerAccessObject. Pour de plus amples informations concernant
cette fonction qui se trouve dans le fichier QCUtilities.js, consultez le Chapitre 5.
Le troisime paramtre de la mthode makeCall est un indicateur boolen qui prcise si le
cache du client, dans ce cas le UIWebView, doit tre utilis ou non. Pour la mthode
setData, la mise en cache tant videmment une mauvaise ide, la valeur de ce paramtre
est fige true de manire dsactiver le cache.
En incluant ces paramtres dans la signature de la mthode makeCall, elle peut encapsuler
efficacement lobtention et lenvoi des donnes un serveur distant. Ce principe de fonction utilitaire servant de faade est souvent employ lorsque, comme dans notre cas, une

iPhone Livre Page 195 Vendredi, 30. octobre 2009 12:04 12

Chapitre 8

Donnes distantes

195

grande partie du code de deux fonctions/mthodes ou plus est presque identique et que,
sans la faade, le code exhiberait une redondance importante.
Tableau 8.2 : API de makeCall

Attribut/mthode

Valeur de retour

makeCall(callType, data- void


Type, refresh, parameterSequence, data,
HTTPHeaders, passThroughParameters)

Description

Paramtres

Cette mthode doit tre


considre comme prive. Elle effectue les
appels AJAX au serveur
et prend en charge les
rsultats.

callType GET ou
POST.
dataType TEXT ou XML.
refresh un boolen
qui indique si une mise
jour force des donnes
depuis le serveur doit tre
effectue.
parameterSequence
une chane qui contient
les paramtres de la
requte ajouts lURL.

data les donnes textuelles ou binaires


envoyes avec la requte.
Ce paramtre est utilis
avec les requtes POST.

HTTPHeaders un
tableau associatif contenant les noms et les
valeurs des en-ttes
envoyer avec la requte.
passThroughParameters un tableau des
valeurs requises par le
framework pour poursuivre le traitement aprs la
rception des donnes
depuis le serveur.

Pour comprendre la mthode makeCall, il est ncessaire de comprendre lAPI de lobjet


JavaScript XMLHttpRequest sous-jacent. Cette API est mise en uvre par la classe UIWebView utilise dans les applications hybrides et la version mobile de Safari.

iPhone Livre Page 196 Vendredi, 30. octobre 2009 12:04 12

196

Dveloppez des applications pour liPhone

Le seul objet dfini par cette API est XMLHttpRequest (voir Tableau 8.3).
Tableau 8.3 : API de XMLHttpRequest

Attribut/mthode

Valeur de retour Description

Paramtres

XMLHttpRequest()

XMLHttpRequest

Le constructeur de lobjet.

Aucun.

abort()

void

Termine la requte.

Aucun.

getAllResponseHeaders()

String

Cette mthode retourne une


chane qui contient les noms
et les valeurs de tous les enttes de la rponse.

Aucun.

getResponseHeader(aHeaderName)

String

Cette mthode retourne une


chane qui contient la valeur
de len-tte de nom indiqu
ou null si cet en-tte nexiste
pas.

aHeaderName le nom de
len-tte HTTP de la rponse
dont la valeur est recherche.

open(type, URL,
asynch, userName,
password)

void

Ouvre et prpare une


connexion au serveur.

type une chane contenant


la valeur GET ou POST.
asynch un boolen qui prcise si la requte doit tre
asynchrone. Ce paramtre doit
toujours avoir la valeur true.

userName un paramtre
facultatif qui prcise le nom
dutilisateur permettant daccder au fichier ou au rpertoire
indiqu dans lURL.

password un paramtre
facultatif qui prcise le mot de
passe de lutilisateur indiqu
pour accder au fichier ou au
rpertoire indiqu dans lURL.

send(data)

void

Cette mthode associe des


data les informations assodonnes textuelles ou binaires cies la requte.
une requte. Elle est utilise
dans les requtes de type
POST, par exemple pour
lenvoi de fichiers.

iPhone Livre Page 197 Vendredi, 30. octobre 2009 12:04 12

Chapitre 8

Donnes distantes

197

Tableau 8.3 : API de XMLHttpRequest (suite)

Attribut/mthode

Valeur de retour Description

SetRequestHeader(name, value)

void

Une mthode qui peut redfinir les valeurs des en-ttes


standard ou ajouter des enttes personnaliss avec leur
valeur une requte.

onreadystatechange

Un attribut auquel est affect


une fonction. Cette fonction
est invoque lorsque lvnement onreadystatechange
est dclench, cest--dire
chaque modification de readyState.

readyState

Un entier qui reprsente ltat


de la requte effectue. Voici
les valeurs possibles :

0 la mthode send na pas


t invoque.
1 La requte est en cours
denvoi au serveur.
2 La requte a t reue par
le serveur.
3 Une partie de la rponse
envoye par le serveur a t
reue.
4 Lintgralit de la rponse
envoye par le serveur a t
reue.
responseText

Les donnes envoyes par le


serveur sous forme de texte,
sans les en-ttes HTTP de la
rponse.

responseXML

Les donnes envoyes par le


serveur au format DOM XML.
Si les donnes ne sont pas du
XML valide, cet attribut est
null.

Paramtres
name une chane qui repr
sente lidentifiant de len-tte.

value une chane qui


contient la valeur associe au
nom.

iPhone Livre Page 198 Vendredi, 30. octobre 2009 12:04 12

198

Dveloppez des applications pour liPhone

Tableau 8.3 : API de XMLHttpRequest (suite)

Attribut/mthode

Valeur de retour Description

status

Un nombre envoy par le serveur pour indiquer le succs


ou lchec dune requte. Les
plus frquents sont 404 (non
trouv) et 200 (succs). La
liste complte est disponible
ladresse http://www.w3.org/
Protocols/rfc2616/rfc2616sec10.html.

statusText

Une chane gnre par le serveur qui contient un message


correspondant au code dtat.

Paramtres

De cette API, les mthodes les plus employes sont le constructeur, open et send. Le code
suivant donne un exemple simple dutilisation de ces mthodes et dautres attributs.
Il demande la page principale du projet open-source WebKit sous forme textuelle.
Deux points sont remarquer dans cet exemple. Tout dabord, lobjet request est global.
Il peut tre utilis dans la fonction handleResponse, qui est appele automatiquement par
le moteur du navigateur lorsque readyState change. Le code est ainsi plus simple, mais
cela risque de poser un problme si deux requtes sont mises en parallle.
var request = new XMLHttpRequest();
request.onreadystatechange = handleResponse;
request.open(GET,http://webkit.org/, true);
request.sent();
function handleResponse(){
if(request.readyState == 4){
if(request.status == 200){
var result = response.responseText;
// Utiliser result.
}
}
}

En raison de la porte globale de la variable request, cet exemple simple nest pas sr
vis--vis des threads. Puisque les requtes sont asynchrones, il est possible, et fort probable, que des requtes se perturbent. ServerAccessObject encapsule cette variable globale
de manire rsoudre ce problme.

iPhone Livre Page 199 Vendredi, 30. octobre 2009 12:04 12

Chapitre 8

Donnes distantes

199

Le deuxime point concerne lenvoi de la requte une URL complte. Dans un navigateur, un objet XMLHttpRequest peut demander des donnes uniquement au serveur dont il
provient. Lobjet UIWebView utilis dans les applications hybrides ne souffre pas de cette
restriction. Il peut demander des donnes nimporte quel serveur car il nest pas un navigateur. Cela reprsente la fois une aubaine et un flau.
Les navigateurs sont restreints sur ce point pour viter les attaques XSS (cross-site scripting).
Elles peuvent se produire lorsque du JavaScript malveillant est insr dans du contenu
HTML sinon innocent demand par votre application. Puisque UIWebView nest pas un
navigateur, vous tes responsable de la protection de votre application contre ces attaques.
Par chance, le framework QuickConnectiPhone permet dassocier des fonctions de
contrle de la scurit (SCF, Security Control Function), qui sont invoques par ServerAccessObject avant que les rsultats des requtes ne soient passs aux VCF.
La cration de ces SCF est comparable celle des VCF, et leur association se fait avec
mapCommandToSCF. La Section 4 donnera un exemple de cration et dutilisation des SCF.
LAPI de lobjet XMLHttpRequest ne permet pas de forcer une actualisation. ServerAccessObject offre cette possibilit en utilisant lun des attributs HTTP standard de la
requte.
if(refresh){
/*
* Si le cache doit tre dsactiv et lappel au serveur impos,
* len-tte If-Modified-Since doit tre fix une date passe.
*/
http.setRequestHeader( "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT" );
}

Len-tte If-Modified-Since indique au serveur quil doit envoyer les donnes si la date
de modification de llment demand est postrieure celle prcise par cet en-tte. En
fixant la valeur de len-tte une date passe, nous sommes certains que les donnes dans
le cache ne sont pas utilises.
Par ailleurs, lAPI de ServerAccessObject ne permet pas lutilisateur dindiquer si la
requte doit tre synchrone ou asynchrone. Tous les appels AJAX doivent tre asynchrones. De cette manire, le moteur web reste ractif et peut traiter les actions suivantes de
lutilisateur. Si les appels sont synchrones et si lutilisateur pivote liPhone, le UIWebView
affiche un cran blanc. Cela se produit galement si lutilisateur dcide de faire dfiler la
vue pendant quune requte au serveur est en cours. Dans les deux cas, lexprience de
lutilisateur ne sera pas agrable. Lutilisation synchrone de lobjet XMLHttpRequest tant
donc une mauvaise ide, ServerAccessObject impose un traitement asynchrone de
toutes les requtes.

iPhone Livre Page 200 Vendredi, 30. octobre 2009 12:04 12

200

Dveloppez des applications pour liPhone

Contrairement lexemple simple prcdent, ServerAccessObject nutilise pas une


fonction standard pour grer les vnements onreadystatechange. la place, il sappuie
sur une fonction anonyme ; pour de plus amples informations concernant les fonctions
anonymes, consultez le Chapitre 3. La dcision dopter pour une fonction anonyme a t
prise en raison de sa capacit exister dans la porte de la fonction englobante.
Toutes les variables locales dclares dans la mthode makeCall sont galement disponibles la fonction anonyme onreadystatechange. De cette manire, le problme de la
variable globale mentionne prcdemment est rsolu. En affectant la variable http le
nouvel objet XMLHttpRequestObject cr, qui sera utilis dans la mthode makeCall, il
se trouve automatiquement dans la porte au moment de lappel la fonction anonyme
onreadystatechange.
Ceux qui ne sont pas habitus la notion de fonction anonyme risquent de trouver cela
incongru. Ceux qui les manipulent dj y verront un moyen de raliser quelque chose dont
ils ntaient pas capables. Le code suivant contient lintgralit de cette fonction anonyme.
1 http.onreadystatechange = function(){
2
3
if(http.readyState == ServerAccessObject.COMPLETE){
4
// Le reprsentant standard de tous les types de requte.
5
var queryResult = new QueryResult();
6
// Les en-ttes derreurs personnaliss que vous pouvez
7
// envoyer depuis le code du serveur si vous le dcidez.
8
queryResult.errorNumber =
9
http.getResponseHeader(QC-Error-Number);
10
queryResult.errorMessage =
11
http.getResponseHeader(QC-Error-Message);
12
if(http.status!= ServerAccessObject.HTTP_OK
13
&& http.status!= ServerAccessObject.HTTP_LOCAL
14
&& http.status!=
15
ServerAccessObject.OSX_HTTP_File_Access){
16
17
queryResult.errorNumber = http.status;
18
queryResult.errorMessage = "Type daccs erron.";
19
}
20
21
/*
22
* Obtenir les donnes si le serveur indique que
23
* le traitement de la requte a russi ou si
24
* la requte concerne directement un fichier
25
* sur le disque du serveur.
26
* Les obtenir sous forme de texte ou en XML.
27
*/
28
if(queryResult.errorNumber == null){

iPhone Livre Page 201 Vendredi, 30. octobre 2009 12:04 12

Chapitre 8

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

Donnes distantes

201

queryResult.data = http[response+dataType];
if(!dispatchToSCF(passThroughParameters[0],
queryResult.data)){
queryResult.errorNumber =
ServerAccessObject.INSECURE_DATA_RECEIVED;
queryResult.errorMessage =
"Donnes non fiables reues.";
}
}
/*
* Invoquer la prochaine fonction de contrle
* de la liste en passant resultData.
*/
if(window.callFunc){
/*
* Lappel peut tre effectu depuis lextrieur
* dune fonction dispatchToBCF. Dans ce cas,
* il ny a pas de fonction callFunc
* dfinie.
*/
var theResults = new Array();
theResults.push(queryResult);
theResults.push(passThroughParameters);
requestHandler(passThroughParameters[0],
passThroughParameters[2], theResults);
}
}

Les lignes 30 36 du code contiennent les appels aux SCF et aux VCF mentionnes prcdemment. La ligne 30 est comparable au code du contrleur frontal dcrit au Chapitre 2.
En ralit, elle est pratiquement identique la fonction checkValidation dcrite et se
comporte de manire quivalente.
Tout comme un utilisateur peut saisir des donnes errones, un serveur peut envoyer des
donnes corrompues. linstar de checkValidation, checkSecurity est une fonction de
type contrleur dapplication. Elle invoque les SCF qui ont t associes dans le fichier
mapping.js la commande qui est associe la BCF en utilisant ServerAccessObject.
Vous pouvez ainsi appliquer tous les contrles de scurit que vous souhaitez aux donnes
reues depuis un serveur et contrer plus facilement les attaques XSS.
Aprs avoir vrifi les donnes, elles sont ajoutes un objet QueryResult pour que
lapplication puisse poursuivre leur traitement. Cela passe par un appel la fonction
requestHandler. passThroughParameters est utilis ici car il contient la commande qui

iPhone Livre Page 202 Vendredi, 30. octobre 2009 12:04 12

202

Dveloppez des applications pour liPhone

a dclench lappel la BCF et la fonction de contrle doit tre invoque ensuite. En appelant requestHandler, la mthode makeCall de ServerAccessObject garantit que toutes
les fonctions de contrle sont invoques dans lordre o elles ont t associes dans le
fichier mappings.js. Puisque theResults est galement pass, il est disponible toutes les
autres fonctions de contrle. Autrement dit, vous pouvez utiliser les donnes comme bon
vous semble.
Puisque la fonction anonyme onreadystatechange comprend ces deux appels des fonctions de type contrleur dapplication et puisquil sagit de la seule fonction laquelle un
serveur envoie des donnes, elle joue le rle dun contrleur frontal supplmentaire pour
lapplication. Autrement dit, en utilisant ServerAccessObject pour tous les accs des
donnes distantes, vous bnficiez des avantages des communications distantes examines
au Chapitre 2 pour les applications standard.
Ce modle de double contrleur frontal apporte la scurit ncessaire aux applications,
tout en donnant la possibilit dobtenir des donnes depuis nimporte quel serveur. La
Figure 8.3 montre comment ces contrleurs frontaux protgent votre application et vos
donnes.

Vos
ECF

Vos
VCF

<contrleur frontal>

Vos
BCF

Fonction anonyme onreadystatechange

<contrleur frontal>

Utilisateur

handleRequest

Vos
ValCF

Serveur

Vos
SCF

Figure 8.3
Les utilisateurs et les serveurs peuvent fournir des donnes errones lapplication. Le modle du double
contrleur frontal protge le code de lapplication des donnes potentiellement nfastes.

iPhone Livre Page 203 Vendredi, 30. octobre 2009 12:04 12

Chapitre 8

Donnes distantes

203

Section 4 : fonctions de contrle de la scurit


Les SCF sont invoques par ServerAccessObject pour vrifier la validit des donnes
obtenues depuis un serveur. Elles jouent un rle quivalant aux ValCF dcrites au Chapitre 2. Elles suivent galement le mme schma que toutes les autres fonctions de contrle.
Pour quune SCF puisse tre invoque, elle doit tre associe une commande. Par exemple, lapplication peut imposer lutilisateur douvrir une session afin quelle renvoie les
donnes JSON en cas de succs. Voici un exemple de ce type dassociation :
mapCommandToSCF(login, checkForFunctions);

Cela signifie que vous devez galement disposer dune fonction checkForFunctions qui
peut tre appele par checkSecurity.
Puisque la bibliothque json2 est disponible dans le fichier json2.js du groupe QCiPhone,
cette fonction est simple crire.
function checkForFunctions(data){
if(data == JSON.stringify(JSON.parse(data){
return true;
}
return false;
}

Au cours de lanalyse des donnes, la mthode JSON.parse ajoute des caractres supplmentaires dans la chane si elle rencontre des dclarations ou des appels de fonctions. Cela
permet de faire chouer ces dfinitions ou ces appels de fonctions, apportant ainsi une
scurit supplmentaire contre les attaques XSS.
Vos vrifications peuvent exploiter cela en reconvertissant le nouvel objet JavaScript cr
en une chane et en la comparant celle dorigine. Si la comparaison choue, lapplication
sait que les donnes obtenues du serveur contiennent du code malveillant.
Le texte JSON qui vous est envoy ne peut donc pas contenir les dfinitions ou des appels
de fonctions. Ce point est trs intressant. En effet, si ce ntait pas le cas, vous ne pourriez
jamais dire si les fonctions JavaScript contenues dans les donnes JSON sont de votre fait
ou si du code malveillant a t insr au cours dune attaque XSS.

iPhone Livre Page 204 Vendredi, 30. octobre 2009 12:04 12

204

Dveloppez des applications pour liPhone

En rsum
ServerAccessObject constitue une solution facile et scurise pour obtenir des donnes
partir de sources distantes dans une application hybride. Cette classe apporte une API
simple demploi, comparable celle de DataAccess, qui rduit votre temps dapprentissage.
Grce aux SCF, le code obtenu peut tre vrifi soigneusement avant que vous ne le dclariez
valide.
ServerAccessObject peut obtenir des donnes distantes et les enregistrer par lintermdiaire de DataAccessObject en vue de leur utilisation ultrieure, ou les utiliser directement comme dans le cas de lapplication browserAJAXAccess. Il ouvre galement des
possibilits de synchronisation entre les donnes enregistres sur la machine locale et
celles prsentes sur une machine distante.
ServerAccessObject permet de crer du code qui peut signaler automatiquement un
serveur web lchec du code de lapplication. Vous pouvez galement lutiliser pour raliser des mesures partir de votre application pour liPhone et les envoyer un serveur de
manire rendre lapplication plus rapide et plus simple utiliser.
Grce ServerAccessObject, toutes ces possibilits sont dsormais facilement utilisables
dans votre application hybride installe sur liPhone.

iPhone Livre Page 205 Vendredi, 30. octobre 2009 12:04 12

A
Introduction JSON
JSON (JavaScript Object Notation) apporte des possibilits trs intressantes. Il
permet de convertir des objets et des tableaux JavaScript en chanes de caractres, qui
peuvent ensuite tre transmises sur le rseau ou enregistres dans une base de donnes.
Ces chanes peuvent ultrieurement tre reconverties en objets ou tableaux sur un autre
ordinateur ou aprs avoir t extraites dune base de donnes. Cette capacit srialiser
et charger des objets et des tableaux JavaScript ouvre de nombreuses possibilits.
Cette annexe prsente une API pour la bibliothque JavaScript JSON et fournit quelques
exemples de son utilisation.

Section 1 : les fondamentaux


La transmission dinformations dun systme un autre a toujours reprsent un
problme. Cela devient particulirement vident dans le dveloppement dapplications
web o un serveur peut tre crit dans nimporte quel langage et sexcuter sur diffrents
types dordinateurs. XML a t lun des premiers formats indpendants de lappareil, du
systme dexploitation et du langage propos pour rsoudre ce problme dchange et

iPhone Livre Page 206 Vendredi, 30. octobre 2009 12:04 12

206

Dveloppez des applications pour liPhone

certaines de ses utilisations se sont rvles intressantes. Lutilisation du format XML


pour transfrer des donnes peut sembler exagre, en particulier pour les petits lments
dinformation gnralement envoys avec AJAX. Si vous souhaitez envoyer uniquement
un petit tableau de nombres ou une mappe de cls-valeurs, XML se rvle un peu verbeux.
Ce point a t rsolu, non en inventant une nouvelle technologie, mais en employant une
fonctionnalit des langages interprts.
Tous les principaux langages interprts faiblement typs disposent dune fonctionnalit
dvaluation, par exemple une fonction eval, qui permet dexcuter des chanes de caractres comme sil sagissait dun code source. Cette possibilit est puissante, mais dangereuse. En cas de mauvaise utilisation, elle peut totalement ouvrir lapplication aux pirates
et aux abus. Par ailleurs, tous les principaux langages interprts faiblement typs ont la
possibilit de dfinir des tableaux et des objets sans passer par un mot cl dinstanciation
de type new.
Si vous examinez des exemples JavaScript, vous verrez comment crer un tableau. Voici
comment procder dans une approche oriente objet :
var tableau = new Array();
tableau.push(5);
tableau.push(13);
tableau.push(Bonjour);

La solution suivante nest pas oriente objet :


var tableau = [5,13,Bonjour];

Ces deux exemples crent des tableaux parfaitement identiques. Le deuxime est intressant pour notre prsentation de JSON. Conjugu aux possibilits JavaScript dvaluation
dune chane comme du code, il permet de bnficier de JSON.
Le code suivant cre une chane de caractres qui correspond la manire dont un
programmeur utiliserait la seconde mthode de cration dun tableau. Il sagit non pas du
tableau en soi, mais dune description de ce que doit tre ce tableau.
var uneChaine = "[5,13, Bonjour]";
// valuer la chane.
var tableau = eval(uneChaine);

iPhone Livre Page 207 Vendredi, 30. octobre 2009 12:04 12

Annexe A

Introduction JSON

207

La dernire ligne parse la chane en un code source JavaScript, interprte ce contenu


JavaScript et lexcute. Dans cet exemple simple, la chane se trouve dans la mme
application que lappel la fonction eval et, par consquent, cette utilisation montre
peu dintrt. En revanche, si la chane provient de la partie Objective-C dune application QuickConnectiPhone ou, plus classiquement, dun serveur, lappel eval a plus
de sens.
La cration dobjets est comparable. Dans lapproche oriente objet suivante, un objet est
cr et des attributs lui sont ensuite ajouts :
var objet = new
objet.largeur =
objet.hauteur =
objet.message =

Object();
5;
13;
Bonjour;

Voici la version non oriente objet :


var objet = {"largeur":5,"hauteur":13,"message":"Bonjour"};

Le code suivant est de type JSON :


var uneChaine = {"largeur":5,"hauteur":13,"message":"Bonjour"};
// valuer la chane.
var objet = eval(uneChaine);

Bien que cette procdure soit au cur de JSON, sa mise en uvre par le programmeur
prsente un danger. Par exemple, si la chane a t envoye depuis le code JavaScript vers
le ct Objective-C de QuickConnectiPhone et si elle contient des instructions complexes,
elle peut potentiellement effacer le disque dur.
Des bibliothques JSON ont t dveloppes pour prendre en charge les problmes de
scurit. Celle que nous utilisons dans la partie JavaScript se nomme Json2 et est propose par le fichier json2.js. Json2 est lun des parseurs JSON les plus utiliss en JavaScript. Puisque des donnes sont rgulirement changes avec la partie Objective-C des
applications fondes sur QuickConnectiPhone, vous devez comprendre lAPI de cette
bibliothque.

iPhone Livre Page 208 Vendredi, 30. octobre 2009 12:04 12

208

Dveloppez des applications pour liPhone

Section 2 : une API JavaScript pour JSON


LAPI de Json2, dcrite au Tableau A.1, est simple. Elle est constitue de deux fonctions :
une premire pour convertir un objet ou un tableau en une chane de caractres et une
seconde pour convertir des chanes de caractres en objets.
Tableau A.1 : LAPI de Json2

Fonction

Paramtres

JSON.stringify(entity, replacer, Paramtre obligatoire :


space, linebreak)
entity lobjet, le tableau ou le type primitif JavaScript
convertir.
Paramtres facultatifs :

replacer une fonction ou un tableau qui permet de redfinir la


gnration par dfaut des chanes de caractres pour les valeurs
associes aux cls des entits JavaScript.

space un nombre ou un caractre, comme \t ou &nbsp, utilis pour indenter les entits JavaScript qui sont les valeurs enregistres avec des cls dans dautres entits.
linebreak un ou plusieurs caractres qui remplacent le caractre \n par dfaut, comme \r\n ou <br/>.
JSON.parse(string, reviver)

Paramtre obligatoire :

string la chane JSON convertir en un objet ou un tableau de


JavaScript.
Paramtre facultatif :

reviver une fonction qui met en uvre un comportement


inverse celui de la fonction replacer utilise avec la mthode
stringify.

La premire fonction se nomme stringify. Elle prend plusieurs arguments, mais dans le
cas de QuickConnectiPhone seul le premier est obligatoire. Il sagit de lobjet ou du
tableau convertir en chane de caractres. En voici un exemple :
var chaineJSON = JSON.stringify(objet);

iPhone Livre Page 209 Vendredi, 30. octobre 2009 12:04 12

Annexe A

Introduction JSON

209

La conversion dune chane en objet est tout aussi simple :


var objet = JSON.parse(uneChaine);

Les tableaux sont pris en charge de la mme manire.


Un exemple complet dutilisation de Json2 pour convertir en chanes et parser des objets se
trouve dans le rpertoire Examples/JSON de QuickConnectiPhone (object_JSON_ example.html). La Figure A.1 illustre la conversion dun objet en une chane, qui est ensuite
reconvertie en un objet, ainsi que laffichage de lattribut size de lobjet.
Figure A.1
Convertir un objet en
chane de caractres et
inversement.

Le rpertoire Examples/JSON contient galement lexemple array_JSON_example.html,


qui illustre lutilisation de Json2 avec des tableaux (voir Figure A.2).
Notez que ces deux exemples utilisent les termes standard dans lindustrie pour les fonctions de srialisation et de reconstruction : stringify et parse.
La bibliothque Json2 permet galement de passer des types primitifs, comme des nombres.
Les chanes de caractres sont aussi prises en charge. Ce nest pas le cas de toutes les bibliothques JSON dans tous les langages. La Figure A.3 illustre ces possibilits.
Grce la bibliothque Json2, vous pouvez convertir en chane de caractres nimporte
quel type de donnes, et le reconstruire ensuite. La bibliothque JSON de la partie Objective-C prend galement en charge les types primitifs et les chanes de caractres.

iPhone Livre Page 210 Vendredi, 30. octobre 2009 12:04 12

210

Dveloppez des applications pour liPhone

Figure A.2
Convertir un tableau en
chane de caractres et
inversement.

Figure A.3
Convertir des types primitifs et des chanes de
caractres en chanes de
caractres et inversement.

iPhone Livre Page 211 Vendredi, 30. octobre 2009 12:04 12

Annexe A

Introduction JSON

211

En rsum
JSON constitue une bonne solution pour changer des informations. Il est indpendant de
lappareil, du systme dexploitation et du langage. Il existe des parseurs open-source
gratuits dans tous les langages couramment utiliss, dont certains, comme PHP, les intgrent
directement.
La bibliothque Json2 fournie avec QuickConnectiPhone est facile utiliser et vous
permet dchanger des donnes avec le ct Objective-C dune application hybride.

iPhone Livre Page 212 Vendredi, 30. octobre 2009 12:04 12

iPhone Livre Page 213 Vendredi, 30. octobre 2009 12:04 12

B
Plan de dveloppement
pour QuickConnectFamily
Puisque le dveloppement de QuickConnectiPhone en est ses dbuts, les amliorations
sont frquentes. Il est donc important de suivre de prs les mises jour. Le Tableau B.1
recense les fonctionnalits disponibles au 3 octobre 2009. Vous pouvez consulter la feuille
de route du projet ladresse http://quickconnect.pbworks.com/Porting-Roadmap.
Oui indique que la fonctionnalit est disponible. En cours signifie que la fonctionnalit est
en cours de dveloppement. Prvu signale que la fonctionnalit est envisageable mais que
son dveloppement nest pas commenc. Impossible sapplique une fonctionnalit qui ne
peut pas tre mise en uvre sur lappareil. Les cases qui contiennent un tiret signalent un
travail qui nest pas ralis au moment de lcriture de ces lignes.

Info

Bien que le dveloppement soit prvu pour Windows et Windows Mobile, rien
nest encore commenc et le Tableau B.1 omet donc ces systmes.

Prvu
En cours
Prvu
Oui
Oui
En cours
Oui
Oui

Rseau par cble


de synchronisation

Accs lappareil photo

Golocalisation dimages

Sons systme (lecture)

Enregistrement/lecture
de fichiers audio

Enregistrement/lecture
de fichiers vido

Slecteurs de date/heure
natifs

Cartes Google
embarques

En cours

Impossible

Impossible

Oui

Oui

Prvu

Prvu

Prvu

Oui

Oui

Oui

Prvu

Oui

Prvu

Impossible Impossible

Oui

Oui

Oui

Prvu

Oui

Prvu

Oui

Oui

Bibliothque
de glisser-dposer

Oui

Impossible3

Oui

Impossible2

Impossible

Oui

Oui

Oui

Enveloppe JavaScript
pour les bases de donnes
(SQLite)

En cours

Impossible

Impossible Impossible

Enveloppe AJAX

Oui

Rseau ad hoc

Oui

Prvu

Oui

Oui

Vibreur

Oui

Linux

Impossible Impossible

Oui

Oui

Acclromtre

Oui

Mac

Enveloppe pour les bases de Oui


donnes natives installes
(SQLite)

Oui

Android

Prvu

Impossible

Prvu

En cours

En cours

En cours

Prvu

Prvu

Prvu

Symbian

Prvu

Prvu

En cours

En cours

En cours

En cours

En cours

Prvu

Prvu

Impossible

Impossible

Impossible

Windows

Prvu

Prvu

En cours

En cours

En cours

Prvu

Prvu

Windows Mobile

Prvu

Prvu

Prvu

Prvu

Prvu

Prvu

Prvu

Prvu

Prvu

Palm WebOS1

214

Golocalisation

iPhone

Tableau B.1 : Feuille de route de QuickConnectFamily au 3 octobre 2009

iPhone Livre Page 214 Vendredi, 30. octobre 2009 12:04 12

Dveloppez des applications pour liPhone

Oui
En cours
En cours
Oui
En cours
(bta)
En cours
(bta)
En cours
En cours
En cours
En cours
En cours
(bta)
Oui

Informations sur lappareil

Rseau P2P Bluetooth

Diffusion audio

Balises audio/vido
de HTML5

API pour les contacts

Notification

Lecteur de bibliothque
audio

Slecteur audio natif

Discussion vocale
depuis une application

Courrier lectronique
depuis une application

Dtection de secousse

Copier-coller

Oui

Oui

En cours

Android

Oui

Oui

En cours

En cours

Mac

Oui

En cours

En cours

Linux

En cours

En cours

Symbian

En cours

Windows

En cours

Windows Mobile

Prvu

Prvu

Palm WebOS1

Annexe B

1. Cette version ne peut pas tre fournie tant que le SDK de WebOS ne fait plus lobjet dun accord de non-divulgation.
2. Google ninclut pas lobjet XMLHttpRequest dans son objet WebView. Il existe une solution, mais elle se rvle trs lente.
3. Google ninclut pas les transitions et les animations CSS ncessaires la mise en uvre de cette fonctionnalit. Lutilisation
de JavaScript pour le glisser-dposer est une solution trop lente.

Oui

Bibliothque pour
tableaux et graphiques

iPhone

Tableau B.1 : Feuille de route de QuickConnectFamily au 3 octobre 2009 (suite)

iPhone Livre Page 215 Vendredi, 30. octobre 2009 12:04 12

Plan de dveloppement pour QuickConnectFamily

215

iPhone Livre Page 216 Vendredi, 30. octobre 2009 12:04 12

216

Dveloppez des applications pour liPhone

Dfinitions des termes employs au Tableau B.1 :

Golocalisation. Obtenir les coordonnes de localisation GPS.

Acclromtre. Obtenir les changements dorientation en x, y et z.

Vibreur. Dclencher le vibreur de lappareil.

Rseau ad hoc. Rechercher et communiquer avec les autres appareils du voisinage qui
excutent la mme application.

Enveloppe JavaScript pour les bases de donnes (SQLite). Utiliser les bases de
donnes HTML 5 intgres.

Enveloppe pour les bases de donnes natives installes (SQLite). Utiliser les bases de
donnes SQLite livres avec une application.

Enveloppe AJAX. Une bibliothque AJAX simple demploi pour obtenir des donnes
distantes.

Bibliothque de glisser-dposer. Une bibliothque simple demploi pour que lutilisateur


puisse dplacer, faire pivoter et redimensionner des lments lcran.

Rseau par cble de synchronisation. Accder des donnes et en transfrer avec une
machine de bureau laide du cble de synchronisation.

Accs lappareil photo. Prendre et enregistrer des photos.

Golocalisation dimages. Accder aux informations de golocalisation ajoutes aux


photos prises avec lappareil.

Sons systme (lecture). Jouer des sons brefs (dune dure infrieure 5 secondes).

Enregistrement/lecture de fichiers audio. Enregistrer un fichier audio en utilisant


lappareil et jouer ces fichiers ou les fichiers audio livrs avec lapplication.

Enregistrement/lecture de fichiers vido. Enregistrer un fichier vido en utilisant


lappareil et jouer ces fichiers avec lapplication.

Slecteurs de date/heure natifs. Afficher et utiliser les slecteurs crits en Objective-C


la place des slecteurs JavaScript limits.

Cartes Google embarques. Ajouter des cartes Google personnalises dans une application la place des cartes standard ou de laffichage de lapplication de cartographie.

Bibliothque pour tableaux et graphiques. Une bibliothque simple demploi permettant


dafficher des graphiques en segments, en barres, en secteurs et autres.

Informations sur lappareil. Obtenir les caractristiques de lappareil.

iPhone Livre Page 217 Vendredi, 30. octobre 2009 12:04 12

Annexe B

Plan de dveloppement pour QuickConnectFamily

217

Rseau P2P Bluetooth. tablir un rseau de pair pair en utilisant la connectivit


Bluetooth.

Diffusion audio. Accder des fichiers audio en streaming.

Balises audio/vido de HTML 5. Prendre en charge les nouvelles balises de HTML 5.

API pour les contacts. Accder aux informations disponibles dans lapplication de
gestion des contacts.

Notification. Envoyer des notifications.

Lecteur de bibliothque audio. Exploiter une bibliothque de fichiers audio.

Slecteur audio natif. Afficher et utiliser les slecteurs crits en Objective-C.

Discussion vocale depuis une application. Dmarrer une conversation vocale sans quitter
lapplication.

Courrier lectronique depuis une application. Accder la messagerie lectronique


sans quitter lapplication.

Dtection de secousse. Dtecter si lutilisateur secoue lappareil.

Copier-coller. Prise en charge de cette fonctionnalit.

iPhone Livre Page 218 Vendredi, 30. octobre 2009 12:04 12

iPhone Livre Page 219 Vendredi, 30. octobre 2009 12:04 12

C
Plan de dveloppement
pour PhoneGap
Puisque le dveloppement de PhoneGap en est ses dbuts, les amliorations sont
frquentes. Il est donc important de suivre de prs les mises jour. Le Tableau C.1 vient du
wiki PhoneGap. Il recense les fonctionnalits disponibles et prvues, telles quindiques
par les dveloppeurs de ce framework. Vous pouvez consulter la feuille de route du projet
ladresse http://phonegap.pbworks.com/Roadmap.
Oui indique que les fonctions JavaScript existent dans PhoneGap au 3 octobre 2009.
Lauteur nest pas en mesure de commenter la disponibilit pour la plate-forme Blackberry. En cours signifie que lquipe PhoneGap travaille sur la fonctionnalit. Les cases
qui contiennent un tiret signalent un travail qui nest pas ralis et qui nexiste pas encore.
Impossible concerne les fonctionnalits que les dveloppeurs considrent indisponibles
sur lappareil.

iPhone Livre Page 220 Vendredi, 30. octobre 2009 12:04 12

220

Dveloppez des applications pour liPhone

Info

Bien que le dveloppement soit prvu pour Windows Mobile, rien nest encore
commenc et le Tableau C.1 omet donc ce systme.

Tableau C.1 : Feuille de route de PhoneGap au 3 octobre 2009

iPhone

Android

Blackberry (OS
4.5)

Symbian

Golocalisation

Oui

Oui

Oui

Oui

Acclromtre

Oui

Oui

Disponible dans
OS 4.7

En cours

Appareil photo

Oui

En cours

En cours

Vibreur

Oui

Oui

Oui

Oui

Hors ligne (fichiers


locaux)

En cours

Oui

En cours

API pour les contacts

Oui

Oui

Oui

Enveloppe SQLite

Oui

Impossible

API XMPP

En cours

E/S du systme de fichiers

En cours

En cours

Geste/toucher multiple

Oui

API SMS

En cours

API de tlphonie

En cours

En cours

En cours

Copier-coller

Oui

Sons (lecture)

Oui

En cours

En cours

Sons (enregistrement)

En cours

Bluetooth

Connexion Wi-Fi ad hoc

Cartes

Oui

En cours

En cours

Changement dorientation Oui

En cours

Disponibilit rseau

Oui

En cours

Magntomtre

Oui (modle
3GS)

En cours

iPhone Livre Page 221 Vendredi, 30. octobre 2009 12:04 12

Chapitre C

Plan de dveloppement pour PhoneGap

221

Dfinitions des termes employs au Tableau C.1 :

Golocalisation. Obtenir les coordonnes de localisation GPS.

Acclromtre. Obtenir les changements dorientation en x, y et z.

Appareil photo. Prendre et enregistrer des photos.

Vibreur. Dclencher le vibreur de lappareil.

Hors ligne (fichiers locaux). Fichiers HTML, CSS et JavaScript installs avec lapplication (non sur un serveur web).

API pour les contacts. Accder aux informations disponibles dans lapplication de
gestion des contacts.

API XMPP. Messageries de type Jabber.

E/S du systme de fichiers. Lire et crire des fichiers textuels ou binaires.

Geste/toucher multiple. Utiliser un ou plusieurs doigts pour la saisie de donnes


complexes.

API SMS. Messagerie instantane.

API de tlphonie. Passer des appels tlphoniques.

Copier-coller. Dupliquer des donnes saisies.

Sons (lecture). Jouer des fichiers audio.

Sons (enregistrement). Enregistrer des fichiers audio laide de lappareil.

Bluetooth. Utiliser la connectivit Bluetooth avec dautres appareils.

Connexion Wi-Fi ad hoc. Rechercher et communiquer avec dautres appareils.

Cartes. Utiliser des cartes Google.

Changement dorientation. Dtecter le passage en modes portrait et paysage.

Disponibilit rseau. Dtecter si lappareil a accs au rseau.

Magntomtre. Obtenir les informations de la boussole intgre.

iPhone Livre Page 222 Vendredi, 30. octobre 2009 12:04 12

iPhone Livre Page 223 Vendredi, 30. octobre 2009 12:04 12

Index

Symboles
__(double soulign) 117
__gap, variable 117
__gap_device_model, variable
117

A
abort, mthode 196
accel, commande 94
Acclromtres
PhoneGap 130
QuickConnectiPhone 94
Accs
aux bases de donnes
BrowserDBAccess,
application dexemple
151-153
dans WebKit 161-172
natives 172-182
SQLite avec WebView
153-158
SQLite natives 158-161

vue densemble 151


aux donnes distantes
BrowserAJAXAccess,
application dexemple
186-188
fonction de contrle de
la scurit 203
ServerAccessObject 188
Voir ServerAccessObject
vue densemble 185
Actualisation de laffichage
visible 36
add, fonction 38
Affichage
cartes gographiques 133138
slecteurs 97
AJAX 187
Anonymes, fonctions 161
Appareil, activation
en JavaScript 92-98, 115122

en Objective-C 98-106,
122-130
applicationDidFinishLaunching,
mthode 22, 24
Applications
dexemple
BrowserAJAXAccess
186-188
BrowserDBAccess
151-153
dimmersion 69-70
hybrides
bote dalerte et 8
dfinition 1
non fondes sur les listes
64-68
Approvisionnement 16
Arrter la lecture des
enregistrements 95
Asynchrone, dfinition 49
AudioServicesPlaySystemSound, fonction 124

iPhone Livre Page 224 Vendredi, 30. octobre 2009 12:04 12

224

Dveloppez des applications pour liPhone

B
Balayement 59
Base de donnes
BrowserDBAccess,
application dexemple
151-153
de WebKit 161-172
Database, objet 163-165
dbAccess, mthode 163
exemple de code 170
generatePassThroughParameters, fonction 163
getData, mthode 162
passThroughParameters,
tableau 163
setData, mthode 162
SQLError, objet 169
SQLResultSet, objet 167
SQLResultSetRowList,
objet 167-169
SQLTransaction, objet
165
natives 172-182
API SQLite3 175
getDeviceData,
mthode 173
getNativeData, mthode
173
makeCall, fonction 174
SendDBResultVCO,
objet 181
setNativeData, mthode
173
SQLite avec WebView
153-158
SQLite natives 158-161
terminologie 152
vue densemble 151
BCF (Business Control
Function) 36, 38, 42, 50

Bote dalerte
applications hybrides et 8
PhoneGap 119
BrowserAJAXAccess,
application dexemple 186188
BrowserDBAccess,
application dexemple 151153

C
calculateSolutionsBCF,
fonction 39
callFunc, fonction 52
Cartes gographiques
afficher dans une application JavaScript
QuickConnect 133-138
module de QuickConnect
138-149
zoom 144-148
Chanes de caractres
convertir des objets/
tableaux en 208
convertir en objets 209
Champs de base de donnes
152
changeView, fonction 63
checkNumbersValCF,
fonction 41
checkSecurity, fonction 201
Classes
DataAccessObject
bases de donnes de
WebKit 161-172
bases de donnes
SQLite avec WebView
153-158

bases de donnes
SQLite natives 158-161
mthodes 154
GlassAppDelegate 23
QuickConnectViewControl
-ler 22
singletons 107
SQLiteDataAccess 172-182
Cls
trangres 153
primaires 153
code, attribut (SQLError) 169
Comportements standard 59
Contenu web, embarquer
avec PhoneGap 29-30
avec QuickConnectiPhone
25-29
Contrleurs
daffichage 49-53
dapplication 41
derreur 53-54
mtier 49-53
Conversion
chanes de caractres en
objets 208, 209
objets en chanes de
caractres 208
Copie de fichiers 13
Cube, transition 67

D
Dashcode 8
modle
QuickConnectiPhone 810
rpertoires 14
transitions 66

iPhone Livre Page 225 Vendredi, 30. octobre 2009 12:04 12

Index

DataAccessObject, classe
base de donnes de WebKit
161-172
Database, objet 163-165
dbAccess, mthode 163
exemple de code 170
generatePassThroughParameters, fonction 163
getData, mthode 162
passThroughParameters,
tableau 163
setData, mthode 162
SQLError, objet 169
SQLResultSet, objet 167
SQLResultSetRowList,
objet 167-169
SQLTransaction, objet
165
base de donnes SQLite
avec WebView 153-158
natives 158-161
mthodes 154
DataAccessObject, mthode
154
DataAccessObject.js, fichier
153
Database, objet 163-165
dbAccess, mthode 163, 169
Dfiler, transition 66
Dlgus 19
deleteScoreBCF, fonction 158
Dplacement 87
Dveloppement, outils
PhoneGap
feuille de route 219
ressources en ligne 5
vue densemble 1-2
QuickConnectiPhone
feuille de route 213

ressources en ligne 5
vue densemble 1-2
Device.exec, fonction 119
Device.init, mthode 117
Device.Location.init, mthode
120
Device.vibrate, mthode 119
Diapositive, transition 67
didAccelerate, mthode 130
didUpdateToLocation,
mthode 130
dispatchToBCF, fonction 49, 50
dispatchToECF, fonction 54
dispatchToValCF, fonction 45
dispatchToVCF, fonction 53
displayScoresVCF, fonction
156, 160
displaySiteDataVCF, fonction
190, 191, 192
displaySolutionVCF, fonction
39
Dissolution, transition 66
doCommand, mthode 104,
110, 111, 139, 181
DollarStash, application
dexemple 69
done, mthode 75
Donnes distantes, accder
BrowserAJAXAccess,
application dexemple
186-188
fonctions de contrle de la
scurit (SCF) 203
ServerAccessObject, classe
188-193
displaySiteDataVCF,
fonction 190, 191, 192
getData, mthode 188,
193
getSiteDataBCF,
fonction 189
makeCall, mthode
193, 195, 196

225

onreadystatechange,
fonction anonyme 200,
201
ServerAccessObject,
mthode 188
setData, mthode 189,
193
XMLHttpRequest, objet
196, 198
vue densemble 185
Donnes, obtenir 36
Double soulign (__) 117
Double-touchers, avec les
cartes gographiques 143
dragAndGesture, application
dexemple 79

E
ECF (Error Control Function)
39, 43, 53-54
changer, transition 67
Embarquer
contenu web
PhoneGap 29-30
QuickConnectiPhone
25-29
Google Maps 133-138
Enregistrements
audio
arrter 95
lire en JavaScript 95
de base de donnes 152
entryECF, fonction 39
eval
fonction 42
type 206
executeSQL, mthode 166,
170

iPhone Livre Page 226 Vendredi, 30. octobre 2009 12:04 12

226

Dveloppez des applications pour liPhone

F
Faire pivoter, transition 67
Feuilles de route
PhoneGap 219
QuickConnectiPhone 213
Fichiers
copier 13
DataAccessObject.js 153
ServerAccessObject.js 189
Fonctionnalits dune
application, tapes de
cration 54
Fonctions
anonymes 161
checkSecurity 201
dassociation, API 40
de contrle de laffichage
(VCF) 36
displayScoresVCF 156,
160
de contrle de la scurit
(SCF) 203
de contrle de la validation
(ValCF) 36
de contrle des erreurs
(ECF) 39
de contrle mtier (BCF)
36
de contrle, modularit 36
de rotation 77
deleteScoreBCF 156-158
dispatchToVCF 53
displayScoresVCF 156,
160
displaySiteDataVCF 190,
191, 192
generatePassThroughParameters 163
getSiteDataBCF 189

makeCall 174
onreadystatechange 200,
201
parse 208, 209
requestHandler 201
stringify 208
Fondu, transition 67
Frameworks 34
FrontController, API 37

gotAcceleration, fonction 121


GPS
JavaScript 96
Objective-C 103, 104, 105
PhoneGap 120, 126
QuickConnectiPhone 96,
121
Groupes Xcode 14
Guide de linterface utilisateur
57

G
generatePassThroughParameters, fonction 163
Gestes 59, 76
getAllResponseHeaders,
mthode 196
getData methodgetData,
mthode 154, 193
getData, mthode 156, 162,
188
getDeviceData, mthode 173
getGPSLocation, fonction 96
getInstance, mthode 108
getNativeData, mthode 155,
160, 173
getResponseHeader, mthode
196
getSiteDataBCF, fonction 189
GlassAppDelegate, classe 23
Glisser-dposer 59
API 78
modules 78-89
sautillement des lments
73
goForward, mthode 64
Google Maps, dans une
application JavaScript
QuickConnect 133-138
goSub, fonction 64

H
handleRequest, fonction 37,
44
handleRequestCompletionFromNative, mthode 182
HIG (Human Interface Guide)
57-61
HistoryExample, application
dexemple 61
Hybrides, applications, bote
dalerte et 8

I
Imagerie mdicale,
applications 69
Immersion, applications 6970
InfoWindow, classe 138, 149
initWithContentsOfFile,
mthode 127
initWithFrame:andLocations,
mthode 138
insertID, attribut
(SQLResultSet) 167
Instanciation dobjets en
Objective-C 16
Instructions prpares 157

iPhone Livre Page 227 Vendredi, 30. octobre 2009 12:04 12

Index

Interfaces
applications fondes sur les
vues 63, 64
interfaces fondes sur les
listes 61-64
transformations CSS 71-78
vues 64
Interrupteurs 60
isDraggable, attribut 81
item, mthode 168

J
JavaScript
activation de lappareil 9298, 115-122
modularit 33-34
exemple QuickConnect
35-43
scroll, fonction 141
JavaScript Object Notation
Voir JSON
JSON (JavaScript Object
Notation) 95, 192
activation de lappareil en
Objective-C 101
API Json2 208-209
vue densemble 205-207
Json2, API 208-209
JSONStringify, mthode 181

L
Lecture
enregistrements audio en
JavaScript 95
sons systme en ObjectiveC 102

length, attribut
(SQLResultSetRowList)
168
Listes
applications non fondes
sur 64-68
interfaces fondes sur 61-64
loadView, mthode 25

M
makeCall, fonction 92, 93, 174
makeCall, mthode 193, 195,
196
makeChangeable, fonction 79,
81
makeDraggable, fonction 78,
80
Mandant-dlgu, relations 19
Mandants 19
Mandataires 19
mapCommands, mthode 102
mapCommandToCO,
mthode 112
MapView, classe 138
math, commande 37, 39
message, attribut (SQLError)
169
Mthodes
abort 196
applicationDidFinishLaunching 22
DataAccessObject 154
dbAccess 163, 169
de rappel 127
doCommand 181
executeSQL 166, 170
getAllResponseHeaders
196
getData 154, 156, 162,
188, 193

227

getDeviceData 173
getNativeData 155, 160,
173
getResponseHeader 196
handleRequestCompletion
FromNative 182
item 168
JSONStringify 181
makeCall 193, 195, 196
open 196
openDatabase 164
readyState 197
responseText 197
responseXML 197
send 197
ServerAccessObject 188
setData 154, 155, 156,
162, 189, 193
setNativeData 155, 173
SetRequestHeader 197
sqlite3_bind_blob 177
sqlite3_bind_double 178
sqlite3_bind_int 178
sqlite3_changes 176
sqlite3_close 175
sqlite3_column_blob 177
sqlite3_column_bytes 177
sqlite3_column_count 175
sqlite3_column_double
176
sqlite3_column_int 176
sqlite3_column_name 175
sqlite3_column_text 177
sqlite3_column_type 176
sqlite3_errmsg 175
sqlite3_finalize 177
sqlite3_open 175
sqlite3_prepare_v2 175
sqlite3_step 176
sqlite3_stmt 175

iPhone Livre Page 228 Vendredi, 30. octobre 2009 12:04 12

228

Dveloppez des applications pour liPhone

Mthodes (suite)
stringByEvaluatingJavaScr
iptFromString 182
transaction 164, 170
XMLHttpRequest 196
Modles
QuickConnectiPhone
pour Dashcode 8-10
pour Xcode 12-16
Modularit
fonctions de contrle 36
JavaScript 33-34
exemple QuickConnect
35-43
implmenter dans
QuickConnectiPhone
44-48
Modules
dfinition 34
glisser-dposer 78-89
redimensionnement 78-89
rotation 78-89
moveX:andY, mthode 147

N
Natives, bases de donnes
accder 172-182
API SQLite3 175
getDeviceData,
mthode 173
getNativeData, mthode
173
makeCall, fonction 174
SendDBResultVCO,
objet 181
setNativeData, mthode
173
SQLite, accder 158-161
Navigateur, partie 61-64
NSLog, fonction 111

O
Objective-C 16-19
activation de lappareil 98106, 122-130
architecture de
QuickConnectiPhone
107-113
instancier des objets 16
module de cartographie de
QuickConnect 138-149
slecteurs 106
structure dune application
PhoneGap 23-25
QuickConnectiPhone
19-22
Objets
convertir des chanes de
caractres en 209
convertir en chanes de
caractres 208
crer 207
Database 163-165
instancier en Objective-C
16
SendDBResultVCO 181
ServerAccessObject 188
SQLError 169
sqlite3 175
SQLResultSet 167
SQLResultSetRowList
167-169
SQLTransaction 165
XMLHttpRequest 196, 198
oldScale, attribut 82
ongesturechange, vnement 86
onreadystatechange
attribut 197
fonction anonyme 200, 201
ontouchchange, gestionnaire
74

ontouchend, gestionnaire 75
open, mthode 196
openDatabase, mthode 164

P
parse, fonction 208, 209
passThroughParameters,
tableau 163
PhoneGap 8, 9
acclromtres 130
activation de lappareil
en JavaScript 115-122
en Objective-C 122-130
API JavaScript 118
bote dalerte 119
embarquer du contenu web
29-30
feuille de route 219
GPS 120, 126
ressources en ligne 5
signaler un
dysfonctionnement
lutilisateur 119
son systme 128
structure Objective-C dune
application 23-25
vibreur 117, 124
vue densemble 1-2
Pin, classe 138, 142
Pincement 59
play, commande 93
playSound
commande 93
mthode pour PhoneGap
122
playTweetSound, fonction
121
Pointeurs 17
prepareDrag, fonction 82

iPhone Livre Page 229 Vendredi, 30. octobre 2009 12:04 12

Index

Prpares, instructions 157


prepareGesture, fonction 86
Protocoles 20

Q
QCCommandObject, classe
110
QuickConnectFamily,
programme dinstallation 8
QuickConnectiPhone
acclromtres 94
activation de lappareil
en JavaScript 92-98
en Objective-C 98-106
afficher des cartes 133-138
embarquer du contenu web
25-29
feuille de route 213
GPS 96, 121
implmentation ObjectiveC 107-113
implmenter une
conception modulaire
44-48
modles
Dashcode 8-10
Xcode 12
modularit de JavaScript
35-43
module de cartographie
138-149
ressources en ligne 5
structure Objective-C dune
application 19-22
vibreur 93, 100
vue densemble 1-2
QuickConnectViewController,
classe 22

R
rangeOfString, mthode 125
readyState, mthode 197
Rcursivit, dfinition 52
Redimensionnement, module
78-89
Rpertoires de Dashcode 14
requestHandler, fonction 201
responseText, mthode 197
responseXML, mthode 197
Ressources en lignes
PhoneGap 5
QuickConnectiPhone 5
retVal, tableau 181
Rotation, module 78-89
Rotation, transition 67
rows, attribut (SQLResultSet)
167
rowsAffected, attribut
(SQLResultSet) 167

S
Saisie textuelle de lutilisateur
59
Saut des lments, lors du
glisser-dposer 73
SCF (Security Control
Function) 203
scroll, fonction 141
Slecteurs
afficher 97
Objective-C 106
send, mthode 197
SendDBResultVCO, objet 181
sendloc, commande 105
ServerAccessObject, classe
188-193, 193-202
displaySiteDataVCF,
fonction 190, 191, 192

229

getData, mthode 188, 193


getSiteDataBCF, fonction
189
makeCall, mthode 193,
195, 196
onreadystatechange,
fonction anonyme 200,
201
ServerAccessObject,
mthode 188
setData, mthode 189, 193
XMLHttpRequest, objet
196, 198
ServerAccessObject, mthode
188
ServerAccessObject.js, fichier
189
setData, mthode 154, 155,
156, 162, 189, 193
setMapLatLngFrameWithDes
cription, mthode 148
setNativeData, mthode 155,
173
SetRequestHeader, mthode
197
setStartLocation, fonction 73
shouldStartLoadWithRequest,
fonction 99
showDateSelector, fonction
97
showMap, fonction 136
showPickResults, commande
97
Singletons, classes 107
singleTouch, message 143
Sons systme
JavaScript 93
jouer en Objective-C 102
PhoneGap 128
Sous-prsentations, liste 62
SQLError, objet 169

iPhone Livre Page 230 Vendredi, 30. octobre 2009 12:04 12

230

Dveloppez des applications pour liPhone

SQLite, bases de donnes


avec WebView 153-158
de WebKit 161-172
Database, objet 163-165
dbAccess, mthode 163
exemple de code 170
generatePassThroughParameters, fonction 163
getData, mthode 162
passThroughParameters,
tableau 163
setData, mthode 162
SQLError, objet 169
SQLResultSet, objet
167
SQLResultSetRowList,
objet 167-169
SQLTransaction, objet
165
natives 158-161
SQLite3, API 175
sqlite3, objet 175
sqlite3_bind_blob, mthode
177
sqlite3_bind_double, mthode
178
sqlite3_bind_int, mthode 178
sqlite3_changes, mthode 176
sqlite3_close, mthode 175
sqlite3_column_blob,
mthode 177
sqlite3_column_bytes,
mthode 177
sqlite3_column_count,
mthode 175
sqlite3_column_double,
mthode 176
sqlite3_column_int, mthode
176

sqlite3_column_name,
mthode 175
sqlite3_column_text, mthode
177
sqlite3_column_type,
mthode 176
sqlite3_errmsg, mthode 175
sqlite3_finalize, mthode 177
sqlite3_open, mthode 175
sqlite3_prepare_v2, mthode
175
sqlite3_step, mthode 176
sqlite3_stmt, mthode 175
SQLiteDataAccess, classe
172-182
SQLResultSet, objet 167
SQLResultSetRowList, objet
167-169
SQLTransaction, objet 165
status, messages
(XMLHttpRequest) 198
statusText, chane
(XMLHttpRequest) 197,
198
stringByEvaluatingJavaScript
FromString, mthode 182
stringify, fonction 208
Synchrone, dfinition 49

Touch, classe 72
Touchers
vnements de 72
images pour indiquer 64
simples, avec les cartes
gographiques 143
simples, avec les cartes
gographiques 143
zones 58
touchesBegan, mthode 144
touchesMoved:withEvent,
mthode 140, 147
transaction, mthode 164, 170
Transformations CSS
personnalises, crer 71-78
Transitions 66
translate, fonction 75
Type eval 206

U
UIWebView
API 27
classe 25, 26
Utilisateur
crans visibles, actualiser
36
saisie, valider 36

V
T
Tableaux
convertir en chanes 208
crer 206
passThroughParameters
163
retVal 181
Tables 152
Tlchargement de Xcode 5

ValCF (Validation Control


Function) 36, 38, 43, 48
Valider la saisie de
lutilisateur 36
VCF (View Control Function)
36, 38, 43, 49, 53
Vibreur
PhoneGap 117, 124
QuickConnectiPhone 93,
100

iPhone Livre Page 231 Vendredi, 30. octobre 2009 12:04 12

Index

Vues 64
applications fondes sur
63, 64
secondaires 27

W
WebKit 71
bases de donnes 161-172
Database, objet 163-165
dbAccess, mthode 163
exemple de code 170
generatePassThroughParameters, fonction 163
getData, mthode 162
passThroughParameters,
tableau 163

SQLError, objet 169


SQLResultSet, objet 167
SQLResultSetRowList,
objet 167-169
SQLTransaction, objet
165
webkitTransform, attribut 71,
74
webMapView, attribut 139
WebView, base de donnes
SQLite 153-158
webView:shouldStartLoadWithRequest:navigationType,
mthode 124
webViewDidStartLoad,
mthode 122

231

X
Xcode
groupes 14
modles
QuickConnect 12-16
tlcharger 5
XMLHttpRequest, mthode
196
XMLHttpRequest, objet 196,
198

Z
Zoom, cartes gographiques
144-148

Dveloppez des applications pour

iPhone

avec HTML,
CSS et
JavaScript

Dcouvrez la manire la plus simple et la plus rapide


de dvelopper des applications iPhone !

Dvelopper avec Dashcode et Xcode

Pour crer des applications iPhone, inutile de matriser


lObjective-C : vous pouvez recourir aux technologies
et aux outils du Web que vous utilisez dj
JavaScript, HTML et CSS. Cet ouvrage vous explique
comment combiner les frameworks QuickConnect et
PhoneGap avec le kit de dveloppement dApple
pour crer des applications scurises de grande
qualit destination des iPhone.

GPS, acclromtre et autres fonctions


natives avec QuickConnectiPhone

Modularit JavaScript
Interfaces utilisateur

GPS, acclromtre et autres fonctions


natives avec PhoneGap
Cartes Google
Bases de donnes
Donnes distantes
Introduction JSON
Plan de dveloppement pour
QuickConnectFamily
Plan de dveloppement pour PhoneGap

Lauteur y dtaille le processus de dveloppement,


de la cration de superbes interfaces utilisateur
la compilation, au dploiement et lexcution
des applications. Il prsente des techniques et des
exemples de code conus pour rationnaliser le dveloppement, supprimer la complexit, optimiser les
performances et exploiter toutes les possibilits de
liPhone, de son acclromtre et son GPS sa base
de donnes intgre.
Grce cet ouvrage, les dveloppeurs web pourront
rapidement programmer pour liPhone en exploitant
les outils quils connaissent dj.

propos de lauteur
Lee S. Barney, expert en dveloppement dapplications
mobiles et web, est le crateur du framework
Quickconnect, qui permet de dvelopper des applications
en JavaScript pour liPhone.

Niveau : Intermdiaire
Catgorie : Dveloppement mobile

Les codes sources des exemples sont


tlchargeables sur le site www.pearson.fr.

Pearson Education France


47 bis, rue des Vinaigriers 75010 Paris
Tl. : 01 72 74 90 00
Fax : 01 42 05 22 17
www.pearson.fr

ISBN : 978-2-7440-4096-2