Vous êtes sur la page 1sur 19

Dvelopper pour iPhone : comment dmarrer, utiliser les outils et e e mettre en place un mod`le MVC e

Antony Gardez eve-ingnieur a lINSA de Rouen El` e ` antony.gardez@insa-rouen.fr 21 juin 2009


Rsum e e Ce document a pour but daider les personnes nayant jamais dvelopp pour les plateformes Apple a e e ` se familiariser avec lIDE Xcode, loutil Interface Builder, le langage Objective-C et le framework Cocoa Touch. Il est rdig dans le cadre dune option prise dans la formation ASI de lINSA de Rouen. Laccent e e sera mis sur le dveloppement pour iPhone bien que dvelopper pour Mac OS X soit tr`s similaire. e e e

Introduction

Apple a sorti liPhone 3G le 17 Juillet 2008 en France, et loprateur Orange en a vendu plus dun million e a ` lheure actuelle. En plus dapporter la 3G, cette nouvelle version a permis aux dveloppeurs le souhaitant e de fournir des applications, dveloppes ` laide de liPhone SDK, pour cette plateforme, par le biais de e e a lAppStore. LiPhone SDK permet dexprimenter un nouvel environnement, autant en termes dInterface Homme e Machine, de langage de programmation que de mod`le de distribution des applications. e Dans cet article, mon but est daider un programmeur connaissant la Programmation Oriente Objet e (POO) ` se lancer dans le dveloppement pour iPhone ou Mac. Cet article ne couvre que quelques notions et a e ne saurait en aucun cas remplacer les tutoriels ociels dApple, qui sont dailleurs tr`s complets, disponible e sur liPhone Dev Center (http://developer.apple.com). Pour dvelopper avec le SDK de liPhone, il est e obligatoire davoir un ordinateur Apple quip de Mac OS X. e e Dans un premier temps nous verrons les outils mis ` disposition par Apple pour dvelopper pour iPhone, a e puis nous verrons comment fonctionne le langage objective-C combin au framework Cocoa, pour enn e comprendre la mise en place le Design Pattern MVC et illustrer toutes ces notions avec un exemple de mise en place dune vue permettant linsertion par lutilisateur de noms de joueurs.

Xcode

Xcode est lIDE dvelopp par Apple, quils utilisent eux-mmes pour dvelopper leurs applications. Il e e e e sadapte ` lobjective-C mais galement au C, au Java et autres langages. Comme la plupart des IDE, il a e contient un outil de debug utilisant gdb et compile ses sources ` laide de gcc, qui lui permet dans le cas de la a programmation pour Mac de construire des excutables pour processeurs Intel et PowerPC. Il est livr avec e e Mac OS X et contient galement des outils danalyse des performances ainsi quInterface Builder, loutil de e conception dinterface que nous utiliserons dans ce document et qui est dtaill dans la section 5. e e

Le dveloppement dune application iPhone ` laide de loutil XCode peut se drouler de la mani`re e a e e suivante : Cration du projet. Il est possible de choisir un template qui dni un type dapplication bien dni e e e parmi les suivants : Navigation-based application, OpenGL, Tab bar, View based, Utility (widget), Window-based (base de tous, contient le main ainsi que les chiers ncessaires au dmarrage dun e e projet). Code dans lIDE apr`s avoir fait de la modlisation. LIDE permet lauto-compltion, le refactoring, e e e mais il est galement possible dacher une petite fentre qui reste au premier plan et donne la e e documentation du symbole situ ` lemplacement du curseur ddition. En terme de gestion de projet, ea e il est possible dutiliser directement des gestionnaires de version tels que subversion, cvs ou perforce. Une autre fonctionnalit est appele Snapshot et permet denregistrer ltat actuel des sources dun e e e projet rapidement an de pouvoir y revenir plus tard en cas de mauvaise manipulation, Dnition des vues et des contrleurs. Les vues peuvent tre dnie dans des classes ou utiliser loutil e o e e Interface Builder, an de placer les lments de la vue de mani`re graphique, ee e Test sur le simulateur iPhone directement sur lcran de lordinateur, e Test sur un iPhone. Si ce dernier est reli ` lordinateur, il est possible dutiliser des outils de dbug ea e ainsi que visualiser les performances de lapplication par le biais des outils Shark et Instruments, Distribution de lapplication. Lorsque votre application est prte, il existe deux modes de diusion : e via lappStore o` en mode ad hoc. Le mode ad hoc permet de diuser une application directement ` u a des personnes, avec un maximum de 100 iPhones. Les deux derni`res tapes de ce cycle ncessitent une adhsion au programme de dveloppeur iPhone e e e e e dApple, qui cote 80e par an et donne acc`s ` la diusion dapplication sur lappStore, soit en choisissant u e a de la distribuer gratuitement ou avec un prix dni. Les pays dans lesquels lapplication sera disponible e peuvent tre dnis lors de la mise en ligne de celle-ci. Par dfaut, cest la diusion dans tous les appStore e e e du monde qui est slectionne. e e

Lobjective-C

Lobjective-C est un langage de programmation orient objet et rexif. Apparu quelques annes apr`s e e e e le C++, au dbut des annes 80, il est galement bas sur le C ANSI mais di`re du C++ par sa vision de e e e e e lenvoi dynamique de messages empreint au langage SmallTalk. Utilis ` lorigine dans le syst`me dexploie ea e tation NeXTSTEP de NeXT, entreprise fonde par Steve Jobs ` son dpart dApple, il a t intgr ` Mac e a e ee e ea OS lors de son retour dans la socit ` la pomme. Bien que principalement utilis par Apple, ce langage ee a e existe galement dans le monde linux, o` les biblioth`ques Cocoa/NeXTSTEP sont par exemple remplaces e u e e par GNUstep. Ce langage est une surcouche tr`s stricte au C. Un compilateur pour objective-C compile correctement e tout code C, et les instructions spcique ` lobjective-C sont clairement direncies lors de la programmae a e e tion : elles commencent par exemple par une arobase, et les envois de messages aux objets sont explicits e entre crochets. En objective-C, tout est objet. Le typage est faible, ce qui permet notamment de manipuler toute sorte dobjets par le type gnral id. Lintrospection est ainsi aise, et il est possible denvoyer des messages ` des e e e a objets qui nimplmentent pas la mthode invoque au moment de la compilation. En eet, des proprits e e e ee telles que le forwarding permettent ` un objet de rcuprer le message qui lui est envoy, de lanalyser puis a e e e de lenvoyer a un autre objet. Ces aspects et beaucoup dautres sont dtaills dans la documentation Apple ` e e 2

mais galement sur la page anglaise de wikipedia correspondante ` ce langage. e a Voyons quelques aspects basiques de la programmation oriente objet en objective-C. e

3.1

1 2 3 4 5 6

Le hello world

Le hello world est quasiment le mme quen C. Le code est le suivant : e


#import <stdio.h> int main( int argc, const char argv[] ) { printf ( hello world\n ); return 0; }

 hello.m

On observe quinclude est remplac par import, et que lextension par dfaut des chiers est .m . e e Pour lachage, il est plus courant dutiliser la fonction NSLog, qui prend en argument un objet NSString, qui est la cha de caract`re de lobjective-C. ces cha ne e nes sont notes entre guillemets mais avec une arobase e avant le premier guillemet. Lappel est donc NSLog(@"hello world");.

3.2

Les classes et lenvoi de messages

Les classes sont dcoupes en deux chiers. Le .h contient ce qui est appel linterface de la classe, et le e e e .m contient son implmentation. Voici un exemple simple. e
1 2 3 4 5 6 7 8 9 10 #import <Foundation/Foundation.h> @interface Dimensions : NSObject { int largeur , longueur; } @property int largeur, longueur; (id) initAvecLargeur: ( int ) largeurDim etLongueur: (int) longueurDim; @end

Dimensions.h Dans le chier de dclaration de la classe, on observe plusieurs aspects importants du langage. Tout e dabord, la biblioth`que gnrale ` importer pour utiliser tous les types dnis par Cocoa est le chier Foune e e a e dation/Foundation.h. Celui-ci contient toutes les rfrences des objets NS* (initiales de NeXTSTEP) tels ee que NSObject ou NSString que nous verrons par la suite. Une classe est dnie dans son chier .h par son interface, portant le nom du chier, qui hrite dune e e classe, ici NSObject. Lhritage est symbolis par les deux points ( :). Vient ensuite la dclaration des membres e e e de la classe, qui sont dans cet exemple des type simples du C. Les membres sont par dfaut privs. Il est e e possible de les dnir explicitement publics, privs ou protgs de la mani`re suivante : e e e e e
1 2 3 4 #import <Foundation/NSObject.h> @interface ExempleAcces: NSObject { @public

5 6 7 8 9 10 11

int variablePublique; @private int varPrivee; @protected int varProtected; } @end

Exemple dutilisation des niveaux dacc`s au membres dune classe e ` A la suite de cette dclaration, il est possible de dnir des property, qui spcient la mani`re de gnrer e e e e e e les accesseurs publics pour les membres de la classe. Il est possible de spcier des param`tres, tels que e e readonly si on souhaite que la proprit ne poss`de quun getter et ne puisse donc pas tre modie, mais ee e e e il est galement possible de dnir son comportement vis-`-vis des acc`s concurrents : atomic et nonatomic e e a e permettent de spcier si lobjet doit grer un acc`s simultan par plusieurs threads. e e e e Les constructeurs par dfaut en Objective-C sappellent init. Pour crer un constructeur personnalis, e e e il convient de lappeler par un nom commenant par init. La syntaxe des mthodes dune classe est celle c e du SmallTalk : les arguments apparaissent apr`s des deux points ( :) et sont tous nomms. Le nom de e e notre mthode de la ligne 9 est initAvecLargeur:etLongueur:. Elle retourne un id qui est, comme dni e e prcdemment, un type gnrique permettant de manipuler lintgralit des types objective-C. Enn, le e e e e e e moins qui dbute la ligne permet de dire que cette mthode nest pas une mthode de classe mais dinstance. e e e Pour les mthodes de classes, dnies par exemple par static en java, il faut utiliser un +. e e

Nous avons donc les prototypes des mthodes dinstance dnis de la mani`re suivante : e e e - (typeRetour) nomDeLaMethodeAvecArgument1 : (typeArg1) nomArg1 etAutresArguments : (typeArg2) nomArg2 ; Pour faire une mthode prive, il sut de ne pas la faire appara dans linterface. e e tre Il est important de remarquer que la notion dinterface est dirente de celle dnie dans des langages e e comme Java. En Java, une interface dnit un comportement prcis en imposant la prsence de certaines e e e mthodes dans les classes limplmentant. Cette notion en objective-C est prsente sous le terme Protocol. e e e Par exemple, une classe qui est capable de recevoir et grer les informations retournes par les acclrom`tres e e ee e de lappareil doit suivre le Protocol UIAccelerometerDelegate. En terme de code, voici la mthode pour utiliser ce protocole au sein dune classe : e
1 2 3 4 5 6 #import <Foundation/NSObject.h> @interface MouvementViewController : UIViewController <UIAccelerometerDelegate> { ... } @end

Utilisation du protocole UIAccelerometerDelegate Contrairement aux interfaces Java, il nest pas ncessaire dimplmenter toutes les mthodes dun protoe e e cole objective-C lorsquune classe le suit. Une interface en objective-C est donc la dclaration dune classe au sein dun chier .h, ce qui se rape proche du langage C puisque ces chiers sont ddis ` la dclaration de prototypes de fonctions et sont e e a e appels chiers den-tte. e e Voyons maintenant limplmentation de la classe Dimension dnie prcdemment. e e e e


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #import Dimensions.h @implementation Dimensions @synthesize longueur, largeur ; (id) initAvecLargeur: ( int ) largeurDim etLongueur: (int) longueurDim { self = [super init ]; if ( self ) { self . largeur=largeurDim; self .longueur=longueurDim; } return self ; }

@end

 Dimensions.m

Dans ce chier, comme en C, il est ncessaire dimporter le chier .h correspondant, qui est ici la e ` dclaration de la classe. Il faut ensuite dmarrer limplmentation. A la ligne 5, nous voyons quil est demand e e e e au compilateur de synthtiser les accesseurs pour les property longueur et largeur selon les modalits dnies e e e dans le .h. ` Ensuite, les mthodes sont dnies. A la 8`me ligne, on observe lappel au constructeur de la classe e e e m`re, plac entre crochets. Les envois de message en Objective-C se font entre crochets. Il ne sagit pas e e dappel de mthodes mais bien denvoi de message. En eet, comme expliqu prcdemment, le destinataire e e e e du message peut ne pas avoir dclar cette mthode, et il est galement possible denvoyer un message ` nil, e e e e a qui est justement lquivalent de NULL mais pour les objets objective-C. Nous voyons ensuite des appels e aux accesseurs de linstance, par les commandes self.largeur et self.longueur. En eet lappel est implicite dans cette notation, mais si nous avions ajout le param`tre readonly ` nos property (par exemple en tapant e e a @property (readonly) int largeur, longueur; dans linterface) nous aurions eu lerreur suivante ` la a compilation : error: object cannot be set - either readonly property or no setter found

La gestion des objets et de la mmoire e

Pour illustrer la gestion des objets en objective-C, nous allons utiliser le type Dimension dni prcdemment. e e e Voici un exemple dutilisation de ce type dans une classe dirente : e
1 2 3 4 5 6 ... (Dimensions ) obtenirDimensionsIdealesAvec4Joueurs { Dimensions dim = [[Dimensions alloc] initAvecLargeur:2 etLongueur:2]; return dim; } ...

Utilisation dun objet Dimension dans une mthode dune autre classe e Dans cette mthode dnue dintrt, on constate que lutilisation dun objet se fait toujours par son e e e ee pointeur en objective-C, aussi bien en tant que type de retour que pour son instanciation. Il existe deux mthodes de gestion de la mmoire : manuelle ou automatique. Dans cet exemple, la e e mmoire est gre manuellement : de lespace mmoire est allou lors de lenvoi du message alloc ` la classe e ee e e a 5

Dimensions, puis le constructeur est appel sur lobjet dont la mmoire vient dtre allou. Quand la gestion e e e e est manuelle, il est ncessaire dexplicitement envoyer le message release ` lobjet lorsque celui-ci nest plus e a utilis dans la classe ou fonction en question. e Lorsquun objet est cr ou plac dans une variable, un message retain lui est envoy, et il sait alors ee e e combien de fois il est encore rfrenc. En envoyant release, ce compteur est dcrment, et lorsque lobjet ee e e e e atteint 0 rfrence il est supprim. ee e Il est possible dindiquer que la gestion de la mmoire doit tre automatique ` linstancition dun objet e e a par le biais du message autorelease envoy par exemple ` lobjet dim. e a Il est cependant conseill de grer manuellement la mmoire dans un soucis de performance optimale, e e e notamment sur un appareil comme liPhone qui na pas les capacits techniques dun ordinateur personnel. e Lors de la conception de classes, il est donc important dcrire la mthode appele lors de la suppression e e e dun objet de cette classe, an de dnir le comportement ` tenir vis-`-vis des membres instancis de cette e a a e classe. Voici un exemple de cette mthode : e
1 2 3 4 5 6 (void) dealloc { [nombreJoueurs release]; [ niveauDiculte release ]; ... [super dealloc ]; }

 Exemple de mthode de dsallocation e e

En gnral, il sut de bien envoyer le message dealloc aux objets qui ont t instancis dans le constructeur e e ee e ou durant le cycle de vie de lobjet, tout en terminant par [super dealloc].

4.1

Autres aspects du langage

Nous nentrerons pas plus dans le dtail ici puisque dautres aspects du langage seront expliqus lorsque e e ceux-ci appara trons au l du document, comme par exemple la gestion des inclusions multiples dans la section 5.2 ou la mise en place du MVC dans la partie 6. Pour approfondir, le site http://www.otierney. net/objective-c.html est intressant car il prsente de mani`re concise et tr`s compl`te beaucoup daspects e e e e e du langage.

5
5.1

Interface Builder
Description gnrale et utilisation e e

Apple Interface Builder est loutil de cration dinterfaces fourni avec XCode. Il est utilis pour les IHM e e des applications visant Mac OS X mais galement iPhone OS. e Les interfaces dun projet XCode cres par le biais dInterface Builder sont des chiers dextension xib ee qui sont des chiers XML tr`s complexes. Pour utiliser un de ces chiers, il faut par exemple crer une e e instance de UIViewController ou dune classe lle de cette derni`re en passant en param`tre dinitialisation e e le nom de ce chier xib. Lordre de la dmarche est simple. Dans un premier temps, il faut crer un nouveau chier depuis lintere e face dXCode, en choisissant la section de templates User Interface et slectionner par exemple View XIB. e

Cette partie est reprsent sur la gure 1. e e

Fig. 1 Choix du template pour la cration dune nouvelle vue e Lorsque ce chier est cr, il est intressant de crer un contrleur ddi pour cette vue, de lequel vous ee e e o e e pourrez mettre des objets tels que des champs de texte ou des labels, mais galement des mthodes qui e e seront appeles par la vue en cas de clic ou autre interaction de lutilisateur. Pour cela, la dmarche est la e e mme que prcdemment, mais il faut choisir la section de templates Cocoa Touch Class puis le template e e e UIViewController subclass. Il est intressant de noter quil est possible de gnrer avec ce chier un chier e e e .xib directement congur pour y tre li. Cependant, nous allons voir comme faire le lien entre un contrleur e e e o et une vue par le biais dInterface Builder. Lorsquune classe de contrleur et une vue sont crs, il faut les lier. Pour ce faire, un double clic sur la o ee vue dans XCode ouvre Interface Builder. Une fois celui-ci charg, deux congurations sont ncessaires. Dans e e le fentre reprsente ` gauche sur la gure 2, on retrouve une entit nomme File Owner. En cliquant sur e e e a e e cet lment, linspecteur ache les informations le concernant. Dans notre cas, la vue que nous avons cr ee ee doit appartenir ` notre contrleur : il faut donc slectionner la classe correspondante dans la partie Class a o e Identity dans la partie Identity de linspecteur.

Fig. 2 Fentres permettant le lien entre une vue et son contrleur dans Interface Builder e o

5.2

Cration dun contrleur et probl`me dinclusion multiple en objective-C e o e

Maintenant que le contrleur est assign ` la vue, il faut que le contrleur sache lui aussi qui est sa o e a o vue. Pour cela, un clic droit sur ce dernier permet dacher les lments quil poss`de pouvant tre lis ` ee e e e a une partie de la vue et les mthodes pouvant tre appeles en cas dvnement survenu sur la vue. Il sut e e e e e alors de lui indiquer que sa vue est celle que nous ditons, cest ` dire celle place dans la fentre de gauche e a e e reprsente par la gure 2. La gure 3 prsente un exemple de File Owner ayant des attributs lis ` la vue e e e e a et des mthodes lies ` des vnements. e e a e e

Fig. 3 Exemple de menu contextuel pour un File Owner Voici linterface correspondante ` ce contrleur : a o
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 #import <UIKit/UIKit.h> @class ControleurDeVue; @class Enonces; @interface ReglagesViewController : UIViewController <UITextFieldDelegate> { NSMutableArray nomsJoueurs, sexesJoueurs; UISlider nombreJoueurs, niveauDiculte; UITextField texteldActif ; UILabel niveauDiculteLabel, nombreJoueursLabel; BOOL clavierVisible; UIScrollView vueScroll; ControleurDeVue controleurPrincipal; UIButton aide; } @property @property @property @property @property @property @property @property (nonatomic, retain) IBOutlet UISlider nombreJoueurs, niveauDiculte; (nonatomic, retain) IBOutlet UILabel nombreJoueursLabel, niveauDiculteLabel; (nonatomic, retain) IBOutlet UIScrollView vueScroll; (nonatomic, retain) ControleurDeVue controleurPrincipal; (nonatomic, copy) NSMutableArray nomsJoueurs, sexesJoueurs; (nonatomic, retain) UITextField texteldActif ; (nonatomic, retain) IBOutlet UIButton aide; BOOL clavierVisible;

(void) sEnregistrerEnTantQuObserver; (IBAction)modierNiveauDiculte:(id)sender; (IBAction)modierNombreJoueur:(id)sender; (void) mettreAJourNombreJoueurs: (NSNotication ) notif; (void) mettreAJourNiveauDiculte: (NSNotication ) notif ; (IBAction)validerReglages:(id)sender;

32 33 34

(IBAction) acherAide;

@end

 ReglagesViewController.h

Dans ce chier, nous avons plusieurs aspects intressants. Tout dabord nous constatons lutilisation dun e protocole nomm UITextFieldDelegate, qui dnit les mthodes permettant ` la classe de recevoir les infore e e a mations relatives ` lutilisation dun champ de texte. a Ensuite, les lignes 3 et 4 prsentent une nouvelle instruction : la commande @class. Cette instruction e permet de prciser que lon utilise une classe qui sera par exemple dnie ultrieurement. Ainsi, il nest pas e e e ncessaire dimporter la classe ControleurDeVue pour dnir un membre de ce type. Il sut alors dimporter e e cette classe au moment de limplantation de notre interface, dans le chier .m. Cette technique permet de contourner le probl`me des inclusions multiples du langage C qui nous contraint e normalement ` utiliser des constantes pour dnir si un chier den-ttes a dj` t charg ou non et ainsi ne a e e eae e e pas lappeler de nouveau. Ici, les chiers dinterfaces ne contiennent pas lappel aux autres chiers den-ttes e dnissant des classes. Linclusion multiple na donc jamais lieu. e Enn, certaines lignes de dnition de property contiennent un mot-clef IBOutlet. Ce dernier permet ` e a Interface Builder de savoir ` quels attributs il est possible de lier les lments que nous plaons sur la vue. a ee c De mme, IBAction est un type de retour identique ` void mais qui indique ` Interface Builder que cette e a a mthode peut tre appele depuis la vue. Si on compare cette dnition de classe ` la gure 3, on retrouve e e e e a eectivement les lments voulu dans loutil ddition de vue et il est alors possible de les lier ` des lments ee e a ee tels que des boutons, des sliders et autres. Aux lignes 29 et 30, on remarque un type appel NSNotication. Celui-ci est utilis lors de la mise en e e place du Design Pattern Observer et nous allons en expliquer le fonctionnement dans la section suivante. Pour conclure sur loutil Inteface Builder, celui-ci est un outil de cration dinterface extrmement puise e sant et pratique. Il est tr`s bien intgr ` XCode, mais il faut garder en tte que des interfaces dnies par e e ea e e le biais de tels outils sont statiques, et que pour dnir une vue qui volue par exemple en achant des e e objets initialement absents, il est ncessaire de savoir dvelopper des interfaces dans le code, ce que nous e e prsenterons lors de notre exemple plus loin dans ce document. e

6
6.1

Le MVC sur iPhone


Lorganisation dun projet en MVC

Dans un projet Xcode, lorganisation des classes est libre. Il est donc possible de crer des dossiers dans e lesquels placer le mod`le, les contrleurs et les vues sparment. Le framework Cocoa Touch est tr`s orient e o e e e e MVC. En eet, comme expliqu prcdemment, les classes hritant de UIViewController sont les contrleurs, e e e e o et les chiers .xib sont les vues. Pour le mod`le, il sut donc de crer soit mme des classes hritant de la e e e e classe NSObject. Core Data est un Framework permettant la gestion du mod`le, par exemple en aidant ` e a lutilisation de commandes telles que undo ou en permettant la persistance des donnes du mod`le. Cepene e dant, nous ne dtaillerons pas son utilisation dans ce document. e Dans le Design Pattern MVC, la vue se met ` jour lorsque le mod`le est modi. Le Design Pattern a e e Observer a pour but de permettre au mod`le, qui est dit observable, dinformer directement la vue, qui e est dite observer. En Cocoa, ce Design Pattern est implant par le biais des notication NSNotication. e

Le principe est simple : des objets peuvent envoyer des notications ` un centre de notication, en leur a donnant un nom spcique, par exemple NombreJoueurModieNotication. La vue qui souhaite recevoir e cette notication senregistre aupr`s du centre de notication en prcisant quelle mthode doit tre appele e e e e e pour cette notication. Il est possible de joindre ` une notication un objet de type NSDictionary contea nant des objets lis ` cette notication. Voici un exemple dutilisation pour simplier la mise ` jour de la vue : e a a
1 2 3 4 (void) modierNombreJoueursActif:(int) nouveauNombre { if (nouveauNombre <= [lesJoueurs.joueurs count]) { lesJoueurs .nombreActifs = nouveauNombre; [[ NSNoticationCenter defaultCenter] postNoticationName:@NombreJoueursModieNotication object:self userInfo: [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:lesJoueurs.nombreActifs], @new , nil]]; } }

5 6

Mod`le : envoi dune notication e Dans cet exemple denvoi de notication, on observe que dans un premier temps le centre de notication par dfaut est rcupr, et quil est envoy ` celui ci le message postNoticationName :object :userInfo :. On e e ee ea peut ainsi prciser qui est lexpditeur de la notication, et on voit que userInfo correspond ` linformation e e a que lon souhaite associer, sous la forme dun dictionnaire. Ici, le dictionnaire contient une seule entre, ayant e pour cl la cha new et on y associe le nombre dactifs. Il est important de noter que le nombre doit tre e ne e un objet, et que nous ne pouvons donc pas joindre directement un int. On observe ainsi, comme pour la cration du dictionnaire, un envoi de message ` une classe, ici NSNumber pour crer directement un objet ` e a e a partir dun int. Lintrt de gnrer lobjet de cette mani`re est quil ny a pas ` se soucier de la gestion de ee e e e a la mmoire voqu prcdemment dans la section 4. e e e e e En utilisant des UIViewController et les vue .xib, cest au sein du contrleur que la notication est o rcupre. Cependant, il est possible de crer des classes hritant de la classe UIView et rcuprer alors la e ee e e e e notication directement dans la vue. Mais lutilisation de UIViewController et de xib rduit la limite entre e les vues et les contrleurs et la gestion dynamique de la vue se fait ainsi dans le contrleur. o o Au niveau du contrleur (ou de la vue), il faut dans un premier temps senregistrer aupr`s du centre de o e notication, puis dnir la mthode associe ` la notication dsire. e e e a e e
1 2 3 4 5 6 7 8 9 10 11 ... [[ NSNoticationCenter defaultCenter] addObserver:self selector :@selector(mettreAJourNombreJoueurs:) name:@NombreJoueursModieNotication object:nil]; ... (void) mettreAJourNombreJoueurs: (NSNotication ) notif { NSDictionary info = [notif userInfo ]; // modication du nombre dans le label nombreJoueursLabel.text = [NSString stringWithFormat:@%d participants, [[info objectForKey:@new] intValue]]; ... }

Contrleur ou Vue : rception de la notication o e Nous voyons ici le message ` envoyer au centre de notication. Il est explicitement dit que lon senrea gistre en temps quObserver, on associe une mthode puis on prcise le nom de la notication en question. e e Le param`tre object permet de prciser si lon souhaite recevoir cette notication uniquement dun objet e e prcis, dans le cas ou plusieurs objets peuvent envoyer des notications. Pour dnir la mthode appele, e e e e on constate quil est possible de donner un objet correspondant ` une mthode ` partir de son nom avec a e a linstruction @selector().

10

La mthode correspondante doit accepter comme argument un objet de type NSNotication qui contiene dra lventuel dictionnaire envoy avec la notication. Les lignes suivantes prcisent la dmarche ` adopter e e e e a pour rcuprer une entre de ce dictionnaire. e e e Enn, il existe des centre de notications adapts ` lutilisation de plusieurs processus dans une applicae a tion, et il galement possible de direr lenvoi de la notication. e e

7
7.1

Application : gnrer une liste dynamique de champs de texte e e


Notions et aspects prsents dans lexemple e

Dans cet exemple, le MVC sera mis en place, avec en plus le Design Pattern Observer. Il sera galement e montr comment utiliser des UIScrollPane, notamment dans le cas ou un clavier doit appara pour pere tre mettre de rentrer du texte. Nous allons donc crer une vue, dans laquelle nous mettrons un UIScrollPane pour pouvoir y dposer e e des UITextField en nombre variable (nombre chang par le biais dun UISlider ). e

7.2

Mise en place des chiers ncessaires e

Pour mettre en place cela, il nous faut deux chiers de classe et une vue xib. Il est possible de crer 3 dossiers pour y classer sparment nos mod`le, contrleur et vue, par le bais du e e e e o panneau Groups & Files de XCode. Crons un chier appel ReglagesViewController, contenant une classe e e hritant de UIViewController, puis une classe appele Joueurs, dnie comme suit : e e e
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #import <Foundation/Foundation.h> @interface Joueurs : NSObject { NSMutableArray joueurs; int nombreActifs; } @property (nonatomic, retain) NSMutableArray joueurs; @property int nombreActifs; (id) initAvecNombreMaxJoueurs:(int)nbMaxJoueurs; (void) denirNomJoueurAvecIndex:(int) indexJoueur etNom: (NSString ) nouveauNom; (void) modierNombreActifsAvecNombre: (int) nbActifs; @end

Joueurs.h Cette classe est minimaliste, elle reprsente une classe du mod`le dun jeu quelconque. Lintrt ici est e e ee de lier cette classe ` la vue pour permettre ` cette derni`re dtre ` jour. Le tableau de joueurs est rempli a a e e a de cha nes de caract`res correspondants aux noms des joueurs, avec une capacit totale de nbMaxJoueurs, e e mais seuls nombreActifs joueurs actifs et donc achs dans la vue. e Voici le contenu du chier dextension .m :
1 2 3 4 #import Joueurs.h @implementation Joueurs

11

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

@synthesize joueurs, nombreActifs; (id) initAvecNombreMaxJoueurs:(int)nbMaxJoueurs { self = [super init ]; if ( self ) { String joueur; NSMutableArray t = [[NSMutableArray alloc] initWithCapacity:nbMaxJoueurs]; for ( int i = 0; i < nbMaxJoueurs; i++) { joueur = [NSString stringWithFormat:@Joueur %d, i+1]; [ t addObject:joueur]; } self .joueurs = t; [ t release ]; } return self ; } // methode permettant de mettre a jour le modele et den informer la vue (void) denirNomJoueurAvecIndex:(int) indexJoueur etNom: (NSString ) nouveauNom { if (indexJoueur < [joueurs count]) { if ([ nouveauNom compare:@] == NSOrderedSame) [[ joueurs setValue: [NSString stringWithFormat:@Joueur %d, indexJoueur+1] forKey: indexJoueur]; else [[ joueurs setValue: nouveauNom forKey: indexJoueur]; // On informe la vue en envoyant une notication que recevront les observeurs [[ NSNoticationCenter defaultCenter] postNoticationName:@NomJoueurModieNotication object:self userInfo: [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:indexJoueur], @index, [[joueurs objectAtIndex:indexJoueur], @new, nil]]; } } (void) modierNombreActifsAvecNombre: (int) nbActifs { if (nbActifs <= [joueurs count]) { self .nombreActifs = nbActifs; [[ NSNoticationCenter defaultCenter] postNoticationName:@NombreJoueursModieNotication object:self userInfo: [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:nombreActifs], @new, nil]]; } } (void) dealloc { [joueurs release ]; [super dealloc ]; }

@end

 Joueurs.m

Dans ce chier, il est intressant de regarder la gestion de la mmoire. Au sein du constructeur nous e e initialisons un NSMutableArray (tableau dont les lments peuvent tre modis, par opposition ` NSAree e e a ray sa classe m`re) que nous plaons par la suite dans la variable joueurs de notre classe. En appelant e c self.joueurs, nous faisons appel au setter dni dans le chier den-ttes avec les proprits nonatomic et e e ee retain. Retain correspond ` la mthode utilise pour stocker la variable lors de lappel au setter : cet attribut a e e peut tre retain, copy ou assign. Dans notre cas, retain informe que lors de la rception de largument dans e e le setter on souhaite lui envoyer un message retain. Le compteur est ainsi incrment pour cette instance, e e et ceci explique pourquoi nous pouvons appeler [t release]; sur notre tableau : il lui reste encore une rfrence. ee Par dfaut, nous avons remplis les noms des utilisateurs ` Joueur x, x tant le numro de celui-ci. La e a e e 12

variable nombreActifs indique ceux qui sont vraiment utiliss. Cette technique permet de conserver les noms e dnis pour des joueurs mme lorsque lutilisateur choisit de rduire le nombre dactifs puis de laugmenter e e e a ` nouveau. En ce qui concerne les mthodes envoyant les notications, il est important de remarquer galement que e e la seconde est une sorte de surcharge du setter et devrait tre faite proprement en surchargeant correctement e le setter, mais nous simplions ici le code pour quil soit plus simplement apprhendable. La documentation e ocielle Apple prcise comment surcharger les getter et setter. e Voyons ensuite le contrleur qui est associ ` notre vue. o ea
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 #import <UIKit/UIKit.h> @class Joueurs; @interface ReglagesViewController : UIViewController <UITextFieldDelegate> { NSMutableArray nomsJoueurs; UISlider nombreJoueurs; UITextField texteldActif ; UILabel nombreJoueursLabel; BOOL clavierVisible; UIScrollView vueScroll; Joueurs joueurs; } @property @property @property @property @property @property @property (nonatomic, retain) IBOutlet UISlider nombreJoueurs; (nonatomic, retain) IBOutlet UILabel nombreJoueursLabel; (nonatomic, retain) IBOutlet UIScrollView vueScroll; (nonatomic, retain) NSMutableArray nomsJoueurs; (nonatomic, retain) UITextField texteldActif ; (nonatomic, retain) Joueurs joueurs; BOOL clavierVisible;

(IBAction)modierNombreJoueur:(id)sender; (IBAction)validerReglages:(id)sender;

@end

 ReglagesViewController.h

Tous les lments de la vue sont dclars ici. En ralit, si certains labels ou autres lments de la vue ee e e e e ee ne sont pas utiliss dynamiquement, cest ` dire modis ou supprims, il nest pas ncessaire de les faire e a e e e appara dans le contrleur. Comme nonc prcdemment, il est important de savoir quil nest pas oblitre o e e e e gatoire de grer le contenu de la vue depuis le contrleur mais quil est possible de faire des classes de vue. e o Dans notre exemple, puisque nous utilisons Interface Builder, il est plus simple de tout contrler depuis le o contrleur. o Nous avons ici un nouvel exemple dutilisation de linstruction @class, qui nous permet davoir un attribut de type Joueurs sans avoir ` importer le chier Joueurs.h. a Voyons maintenant limplmentation de cette classe. e
1 2 3 4 5 #import ReglagesViewController.h #import Joueurs.h @implementation ReglagesViewController

13

6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70

@synthesize nombreJoueurs, nombreJoueursLabel, nomsJoueurs, vueScroll, texteldActif, clavierVisible ; // reagit au slider pour mettre a jour le label correspondant et ajouter les champs de texte // necessaires pour rentrer les noms des joueurs (IBAction)modierNombreJoueur:(id)sender { // Selon la position du slider , on interprete dierement le choix de l utilisateur if (nombreJoueurs.value < [controleurPrincipal.laPartie obtenirNombreJoueursActifs] 0.5 || nombreJoueurs.value > [controleurPrincipal.laPartie obtenirNombreJoueursActifs] + 0.5) { // mise a jour du modele en fonction cette modication de la vue [joueurs modierNombreActifsAvecNombre: oor(nombreJoueurs.value + 0.5)]; } } (void) mettreAJourNombreJoueurs: (NSNotication ) notif { // La notication nous permet de recuperer la nouvelle valeur du nombre de joueurs dans le modele NSDictionary info = [notif userInfo ]; int nbJoueursRecu = [[info objectForKey:@new] intValue]; // modication du nombre ache nombreJoueursLabel.text = [NSString stringWithFormat:@%d participants, nbJoueursRecu]; // modication du nombre de textelds aches UITextField tf; // ajout des textelds manquants for ( int i=0; i< nbJoueursRecu; i++) { if (![ tf = [ self .nomsJoueurs objectAtIndex:i] superview]) { // si l objet a l index i n est pas dans la vue principale , i .e. s il na pas de superview, // on l ajoute a la vue [ self . vueScroll addSubview: tf]; } } // retrait des textelds et switchs en trop bool termine = FALSE; int i = nbJoueursRecu; while (! termine && i < [joueurs.joueurs count]) { if ([ tf = [ self .nomsJoueurs objectAtIndex:i] superview]) { [ tf removeFromSuperview]; } else { termine = TRUE; } i++; } // agrandissement de la fenetre scroll [ self . vueScroll setContentSize:CGSizeMake(320, 300 + nbJoueursRecu40)]; } (IBAction)validerReglages:(id)sender { // Passage a la vue suivante, par exemple en appelant une methode sur un controleur principal // possedant ce controleur et dont on aurait ici une reference } // methode appelee grace au protocol UITextFieldDelegate (void)textFieldDidBeginEditing:(UITextField )theTextField { texteldActif = theTextField; } // methode appelee grace au protocol UITextFieldDelegate (void)textFieldDidEndEditing:(UITextField )theTextField { int i = 0; bool trouve = FALSE; while ( i< joueurs.nombreActifs && !trouve) { if ([ nomsJoueurs objectAtIndex:i] == theTextField) trouve = true;

14

71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135

i++; } if (trouve) { [ self denirNomJoueurAvecIndex:i1 etNom:theTextField.text]; } } (void) mettreAJourNomJoueur: (NSNotication ) notif { NSDictionary info = [notif userInfo ]; int index = [[ info objectForKey:@index] intValue]; UITextField t = [nomsJoueurs objectAtIndex: index]; NSString nouveauNom = [info objectForKey:@new]; if ([ nouveauNom compare:[NSString stringWithFormat:@Joueur %d, index+1]] != NSOrderedSame) t . text = nouveauNom; } (void) sEnregistrerEnTantQuObserver { // notication utile pour gerer l arrivee du clavier sur la vue [[ NSNoticationCenter defaultCenter] addObserver:self selector :@selector(keyboardWasShown:) name:UIKeyboardDidShowNotication object:nil]; // notication utile pour gerer l arrivee du clavier sur la vue [[ NSNoticationCenter defaultCenter] addObserver:self selector :@selector(keyboardWasHidden:) name:UIKeyboardDidHideNotication object:nil]; [[ NSNoticationCenter defaultCenter] addObserver:self selector :@selector(mettreAJourNombreJoueurs:) name:@NombreJoueursModieNotication object:nil]; [[ NSNoticationCenter defaultCenter] addObserver:self selector :@selector(mettreAJourNomJoueur:) name:@NomJoueurModieNotication object:nil]; } (void) keyboardWasShown:(NSNotication ) notif { if (! self . clavierVisible ) { NSDictionary info = [notif userInfo ]; // Recuperons la taille du clavier NSValue aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey]; CGSize keyboardSize = [aValue CGRectValue].size; // Redimensionnement de la vue scroll CGRect viewFrame = [vueScroll frame]; viewFrame.size.height = keyboardSize.height; vueScroll .frame = viewFrame; } // On remonte le texteld actif dans une partie visible de l ecran. CGRect textFieldRect = [texteldActif frame]; textFieldRect. origin .y += 40; [ vueScroll scrollRectToVisible :textFieldRect animated:YES]; self . clavierVisible = YES; } (void)keyboardWasHidden:(NSNotication ) notif { NSDictionary info = [notif userInfo ]; // On prend la taille du clavier NSValue aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey]; CGSize keyboardSize = [aValue CGRectValue].size;

15

136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200

// on remet la taille de la vue scroll comme il faut CGRect viewFrame = [vueScroll frame]; viewFrame.size.height += keyboardSize.height; // on met une petite animation [UIView beginAnimations:nil context:NULL]; [UIView setAnimationBeginsFromCurrentState:YES]; [UIView setAnimationDuration:0.3]; vueScroll .frame = viewFrame; [UIView commitAnimations]; self . clavierVisible = NO; } // The designated initializer . Override to perform setup that is required before the view is loaded. (id)initWithNibName:(NSString )nibNameOrNil bundle:(NSBundle )nibBundleOrNil { if ( self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) { // Custom initialization [ self sEnregistrerEnTantQuObserver]; self . clavierVisible = FALSE; } return self ; } // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. (void)viewDidLoad { [super viewDidLoad]; // conguration du scroll de la vue, cf . documentation pour details des dierentes valeurs [ self . vueScroll setCanCancelContentTouches:NO]; self . vueScroll .clipsToBounds = YES; self . vueScroll . indicatorStyle = UIScrollViewIndicatorStyleWhite; // on prend une taille adequate pour acher le contenu qui est dependant du nombre de joueurs actifs [ self . vueScroll setContentSize:CGSizeMake(320, 300 + joueurs.nombreActifs40)]; [ self . vueScroll setScrollEnabled:YES]; nombreJoueurs.minimumValue = 2; // reglage du slider en fonction de la constante du nombre max de joueur dans le jeu // on considere que la variable joueurs de notre controleur a ete remplie depuis la classe qui l a // instancie . Il faudrait creer un constructeur pour ce controleur qui prend en argument cet objet joueurs. if (joueurs != nil ) nombreJoueurs.maximumValue = [joueurs.joueurs count]; else [NSException raise:@Variable non denie format:@la variable joueurs n est pas denie ]; // achage de 4 textelds , et ecriture de 4 participants dans le label adequat. nombreJoueursLabel.text = [NSString stringWithFormat:@%d participants, 4]; nombreJoueurs.value = [controleurPrincipal.laPartie obtenirNombreJoueursActifs]; // mise en place de l achage dynamique des champs texte NSMutableArray tableauTextelds = [[NSMutableArray alloc] init]; UITextField t; NSString chaine; for ( int i=0; i < [joueurs.joueurs count]; i++) { t = [[UITextField alloc] initWithFrame: CGRectMake(40.0, 280.0 + i40, 150.0, 31.0)]; chaine = [[NSString alloc] initWithFormat:@Joueur %d, i+1]; t .textAlignment = UITextAlignmentCenter; t .borderStyle = UITextBorderStyleRoundedRect; t .autocapitalizationType = UITextAutocapitalizationTypeWords; t .keyboardType = UIKeyboardTypeDefault; t .autocorrectionType = UITextAutocorrectionTypeNo; t .returnKeyType = UIReturnKeyDone;

16

201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241

t . delegate = self ; // mise du texte gris par defaut dans le fond du champ texte [ t setPlaceholder:chaine ]; [ tableauTextelds addObject:t]; [chaine release ]; [ t release ]; } self .nomsJoueurs = tableauTextelds; [ tableauTextelds release ]; // achage des textelds du depart for ( int i=0; i< 4; i++) { [ self . vueScroll addSubview:[self.nomsJoueurs objectAtIndex:i]]; } } // Par defaut, le clavier ne se retire pas quand on valide par le bouton en bas a droite // il faut donc lui dire que faire . (BOOL)textFieldShouldReturn:(UITextField )theTextField { [theTextField resignFirstResponder]; return YES; } (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Releases the view if it doesnt have a superview // Release anything thats not essential , such as cached data } (void)dealloc { [nombreJoueurs release]; [nombreJoueursLabel release]; [nomsJoueurs release]; [ vueScroll release ]; [ texteldActif release ]; [super dealloc ]; } @end

 ReglagesViewController.m

Cette classe est assez consquente, cest pourquoi jai choisi de commenter le code directement pour divers e aspects de la programmation. Pour rsumer les enjeux, il faut comprendre deux choses. Dans un premier temps, nous avons dni une e e vue avec Interface Builder dans laquelle nous avons plac une UIScrollView que nous avons li ` sa variable e ea correspondante dans le File Owner qui est de classe ReglagesViewController. Les labels sont eux aussi ` plaa cer dans la vue, manuellement. De plus, il faut comprendre que tous les lments dune vue sont eux-mme ee e des vues : la vue scroll est une vue au mme titre que celle qui la contient, et les champs de textes en sont e galement. Tous ces objets se manipulent donc tous de la mme mani`re, et il est ainsi possible de savoir si e e e un champ texte est ach en lui demandant sa superview. e Ensuite, les dicults lies ` la mise en place dune telle vue sont multiples : e e a Grer lachage dynamique des champs de texte La mise en place de ceux-ci est dclenche par la e e e rception dune notication. En eet, dans le constructeur de la classe nous nous sommes enregistrs en e e tant quobserver de deux notications, qui concernent les modications du mod`le qui nous intresse. e e Lorsque lon reoit la notication qui indique un changement du nombre de joueurs actifs, on sait que c

17

lon doit modier lachage pour adapter celui-ci au mod`le. Pour ce faire, on les positionne dans la e vue scroll en leur xant une taille et un emplacement spciques en pixels. Ainsi, dans une boucle, il e est possible den gnrer un nombre variable. Parall`lement ` a, il faut ajuster la taille dnie pour le e e e ac e contenu dans la vue scroll, et ceci de la mme mani`re que pour les texteld, e e Grer lachage du clavier et le scroll jusquau champ choisi Lorsque le clavier sache, par dfaut e e il se place au dessus de la vue scroll, et ce sans rien faire dautre. Or, le probl`me est dans un premier e temps que le champ slectionn est probablement cach par le clavier, mais galement que le bas du e e e e contenu de la vue scroll ne sera jamais accessible puisque cach. La solution est de redimensionner la e vue scroll pour noccuper que la partie non cache de lcran quand le clavier est visible, et de scroller e e automatiquement dans cette vue pour que le champ de texte dsir se retrouve au dessus du clavier. e e Ces deux techniques sont mises en place dans la mthode keyboardWasShown:, et le retour ` la normal e a est gr par keyboardWasHidden:. Ces deux mthodes se trouvent respectivement aux lignes 108 et ee e 129. Pour que ceci se droule bien, il faut videmment identier le champ qui est actuellement dit. En e e e e crivant la mthode textFieldDidBeginEditing:, ` la ligne 60, puisquon suit le protocole UITexte e a FieldDelegate, on peut savoir quand un champ texte est slectionner et ainsi le stocker dans une variable e pour pouvoir lidentier lors de lapparition du clavier. Lorsque ldition du champ texte est termine, e e on met ` jour le mod`le avec le nouveau nom tap. a e e Cette mthode nest probablement pas parfaite, mais apr`s de longue recherches, elle sav`re tre e e e e une des plus ecaces. Je lai mise au point ` partir de diverses techniques proposes par dautres a e dveloppeurs notamment sur les forum dApple. e Apr`s un travail de prsentation, et en laborant un peu plus le contenu (possibilit de choisir un niveau e e e e de dicult, de dnir les sexes des joueurs), la vue devient comme prsente sur la gure 4. e e e e

Fig. 4 Exemple de rendu de la mthode propose, avant et apr`s le choix dun champ texte e e e Enn, il reste quelques aspects intressants de la programmation en objective-C pour iPhone. la fonction e validerReglages: de la ligne 54 est appele depuis la vue. Son type de retour est IBAction, ce qui permet e comme expliqu prcdemment ` Interface Builder de lidentier comme disponible pour la vue. Largument e e e a reu est de type id. Il sagit de lmetteur de laction. Ainsi, si cette mthode peut tre appele depuis deux c e e e e boutons dans la vue, il est possible de savoir duquel des deux il sagit. Ensuite, en terme de gestion de la mmoire, il est galement possible de parametrer un comportement spcique en cas de probl`me. La e e e e

18

mthode didReceiveMemoryWarning permet de dnir une conduite ` suivre pour allger la charge et viter e e a e e une fermeture force de lapplication. e

Conclusion

Pour un dveloppeur connaissant le C et la programmation oriente objet, la transition ` ce langage est e e a relativement aise. La plus grosse dirence vient plutt de la plateforme elle-mme. En eet, les contraintes e e o e de performance et de sauvegarde de la mmoire permettent au dveloppeur de gagner en concision. Cest e e galement un avant got intressant de ce que peut tre la programmation pour syst`mes mobiles et eme u e e e barqus, et cest ` mon avis une branche intressante de linformatique. e a e Bien que ce document nait pas la prtention de remplacer les documentations ocielles fournies par e Apple, je pense quil rcapitule une grande partie des notions primordiales au dveloppement pour iPhone et e e Mac OS X. Jesp`re enn que ce document pourra aider certains ` dbuter, comprendre un peu mieux e a e certaines notions du langage ou encore rsoudre certains probl`mes de gestion du clavier de liPhone. e e

19

Vous aimerez peut-être aussi