Tutoriel: Créer une application simple pour iPhone sur iOS 5. Partie 2/3

Ray Wenderlich

Cet article est également disponible en : Chinois simplifié, Anglais, Japonais, Espagnol, Coréen

On dirait que cette coccinelle n’est pas très flippante…

On dirait que cette coccinelle n’est pas très flippante…

Mise à jour du 17/02/12: Adaptation à iOS 5.

Ceci est le deuxième article d’un guide en trois parties sur la création d’une application iPhone pour les débutants. L’application que l’on construit parle d’insectes flippants !

Dans la première partie, nous avons créé une application qui contient une liste d’insectes dans une table view.

Dans cette partie, nous allons voir comment créer la vue détaillée, afin d’afficher une image plus grande de nos insectes, les noter, et modifier leur image !

Dans la troisième et dernière partie de cette série, nous verrons comment ajouter des insectes, une icône, une image par défaut et comment gérer les opérations longues en tâche de fond.

Poursuivons notre application « Scary Bugs » pour en ajouter quelques-uns… après tout, c’est en cela que consiste la programmation, non ? ;]

View Controllers, les contrôleurs de vues

Maintenant que nous avons une liste d’insectes, il serait bon de pouvoir toucher l’un d’entre eux pour voir s’afficher un écran sur lequel on pourrait modifier son nom et son image ou lui mettre une note.

La plupart du temps dans les applications iPhone, il y a une classe qui joue le rôle de contrôleur pour chaque « écran » de l’application : un « View Controller ». Pour l’instant, notre MasterViewController apparaît au démarrage, il contient la table view (Plus précisément, c’est la vue gérée par le MasterViewController qui apparaît). Nous voulons faire en sorte que lorsque l’utilisateur touche un insecte de la liste, cela amène une vue détaillée affichant les informations sur l’insecte, cette vue étant gérée par le DetailViewContoller.

Lorsque nous avions lancé pour la première fois l’application issue du modèle de création d’XCode, cela fonctionnait. Mais depuis que nous avons modifié les données attachées à notre table view (notre liste d’insectes plutôt que les objets de type NSDate du projet initial créé par XCode), le fait de toucher une ligne ne permet plus d’afficher l’objet dans la vue détaillée. Nous allons corriger cela bientôt.

Chaque View Controller peut contenir plusieurs vues. Dans le contrôleur de notre table view, nous n’avions qu’une seule vue — la table view. Cependant, dans le contrôleur de notre vue détaillée, nous allons avoir besoin d’un certain nombre de vues : Une pour le nom d’insecte, une pour l’image, une vue également pour la notation, et quelques autres.

Pause téléchargement !

En parlant de notation, nous allons utiliser une vue permettant de noter — de zéro à cinq étoiles — les insectes sur la vue détaillée. L’iPhone ne dispose pas de vue standard de ce type, cependant j’ai écrit récemment un guide qui s’intitule « Comment créer une classe UIView personnalisée pour iOS 5 : Une vue d’appréciation sur 5 étoiles » (en anglais). Nous allons donc partir de la vue créée dans ce guide.

Il n’est pas nécessaire d’aller suivre ce guide maintenant pour poursuivre notre application (sauf si vous en avez envie !), nous pouvons nous contenter de télécharger le résultat du tutoriel mis à disposition dans cette archive

Téléchargez donc le fichier puis faites les choses suivantes :

  • Créez un nouveau groupe nommé « Views »
  • dans XCode, et placez-y les fichiers RateView.h et RateView.m. Assurez-vous que la case « Copy items into destination group’s folder (if needed) » est cochée. Ces fichiers contiennent le code de la vue de classement sur 5 étoiles provenant du tutoriel évoqué.

  • Faites de même avec la classe UIImageExtras, mais placez-la dans un groupe nommé « Helpers » (signifiant « Assistants »). Il s’agit d’une classe qui nous aidera à redimensionner les images plus tard.
  • Insérez dans le projet les images de visages effrayés (fichiers shockedface…) dessinés par ma tendre épouse, en les plaçant cette fois dans un groupe nommé « Art ». Ce sont les images que nous utiliserons à la place des étoiles pour ajouter une petite touche de légèreté. :]
  • Enfin, insérez le fichier logo1.png dans le projet, également dans le groupe « Art ». Nous l’utiliserons plus tard comme icône de l’application.

Mise en forme de la vue Detail View avec l’éditeur de Storyboard

Bien, nous sommes enfin prêts à travailler ! Ouvrez le fichier MainStoryboard.storyboard, et faites défiler l’écran jusqu’à la droite pour voir le Detail View Controller qui a été créé par défaut par XCode lors du choix de modèle d’application « Master-Detail ». La vue contient un libellé indiquant « Detail view content goes here », signifiant « Le contenu de la vue “Detail” doit être placé ici » :

La vue Detail View dans l’éditeur de Storyboard

L’éditeur de Storyboard offre un moyen de construire l’interface de l’application visuellement dans XCode. On y place des éléments d’interface par glisser-déposer, on configure les attributs des éléments comme on le souhaite, et on connecte les éléments ainsi créés à des propriétés de nos classes de type View Controller.

La manière la plus simple de le comprendre est de l’essayer ! D’abord, allez dans le menu « Editor > Canvas > Show Bounds Rectangles » — cela signifie « Afficher les rectangles formant les bordures des éléments » et cela nous permettra de mieux distinguer les détails de mise en forme de nos contrôles à l’écran.

Effacez le libellé qui indique « Detail view content goes here » — nous n’aurons pas besoin de lui !

Ensuite, dans le panneau de droite, en bas, assurez vous que le troisième onglet est sélectionné, pour avoir accès à la bibliothèque d’objets. Glissez des éléments UITextField, UIImageView et UIView sur l’écran en les arrangeant (le champ de texte en haut) comme sur l’image ci-dessous :

Mise en forme de l’interface dans l’éditeur de storyboard

Une fois ceci fait, sélectionnez le champ de texte UITextField et dans la partie haute du panneau à droite, assurez-vous que le quatrième onglet est sélectionné afin de changer quelques attributs du champ de texte.

Changez la police de caractères en choisissant, en face du libellé « Font » les valeurs « Custom / Helvetica / Gras / Size 18.0 », l’alignement de texte au centre. Placez le comportement du Clear Button sur « Appears while editing » (pour afficher un bouton Reset sous forme de petite croix lorsque l’on édite le champ de texte). Choisissez également la valeur « Words » pour l’attribut Capitalization pour que la touche majuscule soit automatiquement activée en début de chaque mot. On obtient ceci :

Attributs du champ de texte

Ensuite, passez à l’inspecteur de taille des éléments (Size Inspector) en cliquant sur le cinquième onglet. Configurez les options de dimensionnement automatique comme suit :

Attributs de dimensionnement automatique

Cela aura pour conséquence d’étendre le champ de texte à la largeur de l’écran lorsque l’affichage sera tourné en mode paysage.

Nous pouvons maintenant configurer notre UIImageView. Dans le quatrième onglet (l’inspecteur d’attributs), assignez la valeur « Aspect Fit » à l’attribut mode. Dans le cinquième onglet (Size Inspector), configurez comme l’indique l’image :

Attributs Autosizing

Cette configuration rend l’emplacement de l’Image View flexible pour remplir l’espace disponible tout en conservant ses marges avec le bord de l’écran. Aussi, l’image sera redimensionnée pour tenir dans le cadre tout en conservant ses proportions initiales.

Pour l’UIView, allez au troisième onglet du panneau latéral (Identity Inspector) et assignez « RateView » à l’attribut Class Identity afin d’associer notre vue de classification en cinq étoiles à cette vue. Ensuite, retournez dans le cinquième onglet (Size Inspector) pour y ajuster la configuration d’autosizing suivante :

Attributs d’Autosizing

Cela a pour effet de permettre à la vue de s’étendre sur la largeur, mais de rester en bas avec les mêmes dimensions verticales.

Jusqu’ici, tout va bien ! Il nous faut encore ajouter quelques contrôles supplémentaires. Nous souhaitons que l’utilisateur puisse toucher la zone de l’UIImageView pour changer l’image.

Il y a plusieurs façons de réaliser cela, la plus simple est de créer un bouton invisible qui recouvre l’UIImageView et le configurer de manière à ce qu’une fonction de notre ViewController soit appelée lorsqu’il est touché par l’utilisateur. Nous pouvons également ajouter un libellé sous la forme de UILabel sous l’image, pour indiquer « Tap to Change Picture » ou « Touchez pour changer l’image » si aucune image n’est affichée.

Déplacez-donc un élément de type Round Rect Button (Bouton aux coins arrondis) à partir de la bibliothèque d’objets. Redimensionnez-le pour lui donner la même taille que l’élément UIImageView. Pour le rendre invisible, allez dans le quatrième onglet du panneau latéral (Attributes Inspector) et changez son type en « Custom ». Enfin, dans le cinquième onglet (Size Inspector), indiquez les mêmes options que pour l’emplacement de l’image :

Attributs d’Autosizing

Finalement, glissez un élément de type UILabel à partir de la bibliothèque, et placez-le au milieu de l’UIImageView. Double-cliquez dessus pour remplacer le texte par « Tap To Change Image. » si vous suivez ce guide en utilisant les données sur les insectes en anglais, ou « Touchez pour changer l’image » si vous préférez adapter les données en français. Choisissez un alignement de texte centré, et placez le libellé en arrière plan par rapport à l’UIImageView : ceci se fait dans le panneau de gauche (présent uniquement dans l’éditeur de storyboard), en modifiant l’ordre des sous-éléments du bloc « Detail View Controller ». Comme indiqué sur l’image qui suit, les éléments sont classés de l’arrière-plan vers l’avant-plan :

Placement du libellé en arrière-plan

Comme pour les autres éléments, il nous faut configurer le dimensionnement automatique dans l’attribut autosizing, comme ceci :

Attributs d’Autosizing

Avant de poursuivre, vous pouvez vérifier que vous avez configuré correctement les règles de dimensionnement automatique en changeant l’orientation au mode paysage. Pour cela, sélectionnez le Detail View Controller dans la liste de gauche, et modifiez l’attribut « Orientation » dans l’inspecteur à droite pour essayer chaque valeur :

Test des règles de dimensionnement automatique au sein de l’éditeur de storyboard

Si quelque chose de se positionne pas correctement, pas de panique : Réorientez la vue verticalement et vérifiez les réglages des paragraphes précédents pour les éléments incriminés.

Pfiou ! Nous avons ajouté tous les contrôles dont nous avons besoin dans l’interface, il nous faut maintenant tout relier à des paramètres d’accès dans notre classe : les accès s’appellent des ourlets.

Pour procéder à cette étape, affichons l’Assistant Editor (second bouton au dessus du libellé “Editor” de la barre d’outils de la fenêtre). Assurez vous que l’éditeur assistant est en mode automatique, il devrait afficher le fichier DetailViewController.h comme sur la capture d’écran ci-dessous :

Affichage de l’éditeur assistant

Glissez en maintenant la touche « Ctrl » enfoncée le champ de texte UITextField vers le contenu du fichier DetailViewController.h, juste avant la terminaison @end. Une fenêtre contextuelle apparaît pour créer l’outlet (l’accès au champ de texte dans le code) sous forme de propriété de notre classe. Nommez ce nouel outlet « titleField » et validez par le bouton Connect.

Connexion du champ de texte à un outlet

Répétez cette opération avec la vue UIImageView (nommez l’outlet « imageView ») ainsi qu’avec notre vue RateView (en nommant l’outlet « rateView »).

Nous avons également besoin de relier notre bouton invisible au code de notre classe, mais plus précisément pour déclencher l’exécution d’une fonction lorsque le bouton est pressé. Procédez comme pour la création des outlets précédents, mais dans la fenêtre popup, choisissez le type de connexion « Action ». Nommez la connexion « addPictureTapped » et validez.

Connexion d’un bouton dans l’éditeur de Storyboard

Remarquez que la valeur sélectionnée par défaut pour le type d’événement est « Touch Up Inside ». Cela signifie que l’action sera déclenchée si le bouton est touché et que le doigt de l’utilisateur ne s’est pas déplacé hors de la zone du bouton avant de se relever. Le déclenchement de l’action consistera à exécuter la méthode addPictureTapped de notre classe.

Nous allons faire une autre connexion à notre classe. Nous souhaitons pouvoir changer le contenu du champ de texte, il nous faut créer une action pour cela.

De la même manière que pour le bouton, déplacez le champ de texte UITextField vers notre classe en maintenant la touche « Ctrl ». Choisissez un type de connexion « Action ». La valeur par défaut pour le type d’événement est « Editing Did End », remplacez-la par « Editing Changed » (la valeur par défaut se déclenche en fin d’édition, nous souhaitons plutôt déclencher l’action lorsque le contenu change). Validez.

La dernière chose que nous ayons besoin de faire est d’assigner notre classe comme delegate (responsable) du champ de texte. Parfois, l’association d’une fonction à une action ne suffit pas, de nombreux objets ont besoin d’un delegate à qui ils enverront des messages, des informations. Le UITextField en est un.

Pour faire cette association, faites un « Ctrl-Clic » sur l’élément Text Field de la liste des composants du Detail View Controller. Ensuite, faites une ligne en glissant le cercle en face de l’outlet « delegate » jusqu’à l’élément Detail View Controller (ce dernier sera alors associé en tant que delegate).

Assignation du delegate au champ de texte

À ce stade, voter fichier DetailViewController.h devrait ressembler à ceci :

#import <UIKit/UIKit.h>
 
@interface DetailViewController : UIViewController
 
@property (strong, nonatomic) id detailItem;
 
@property (strong, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
@property (weak, nonatomic) IBOutlet UITextField *titleField;
@property (weak, nonatomic) IBOutlet RateView *rateView;
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
- (IBAction)addPictureTapped:(id)sender;
- (IBAction)titleFieldTextChanged:(id)sender;
 
@end

Vous remarquerez des types d’objets qui vous sont peut-être inconnus — IBOutlet et IBAction. Ce sont les mots-clés “magiques” que l’éditeur de storyboard recherche pour prendre en compte les possibilités d’associations entre nos propriétés de classe et les éléments qui constituent l’interface graphique. Lorsqu’une propriété de type IBOutlet ou IBAction est créée dans une classe, l’éditeur de storyboard (équivalent de l’ancien Interface Builder) les détecte et affiche la possibilité d’associer les éléments.

Comme nous avons créé les outlets à partir de l’éditeur de storyboard, cette association est déjà faite.

Nous avons besoin de faire quelques modifications à ce fichier pour indiquer que notre DetailViewController implémente des protocoles de délégation (cela signifie simplement que notre classe devra disposer des fonctions attendues par les objets dont nous sommes le delegate, rien de très compliqué). Nous allons également ajouter une propriété pour l’image picker permettant la sélection d’une image. Enfin, il nous faut modifier la propriété detailItem pour indiquer qu’il s’agit d’un objet de type ScaryBugDoc. Remplacez donc le contenu du fichier par ceci :

#import <UIKit/UIKit.h>
#import "RateView.h"
 
@class ScaryBugDoc;
 
@interface DetailViewController : UIViewController <UITextFieldDelegate, RateViewDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate>
 
@property (strong, nonatomic) ScaryBugDoc * detailItem;
@property (strong, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
@property (weak, nonatomic) IBOutlet UITextField *titleField;
@property (weak, nonatomic) IBOutlet RateView *rateView;
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (strong, nonatomic) UIImagePickerController * picker;
 
- (IBAction)addPictureTapped:(id)sender;
- (IBAction)titleFieldTextChanged:(id)sender;
 
@end

Nous avons fini la mise en place des éléments d’interface et leur déclaration — direction l’implémentation !

Implémentation de notre Detail View

Nous allons faire de nombreux changement au fichier DetailViewController.m. Comme il y a beaucoup de lignes de code, passons les en revue morceau par morceau.

1) Imports en entête

// En haut du fichier
#import "ScaryBugDoc.h"
#import "ScaryBugData.h"
#import "UIImageExtras.h"
 
// Ajouter dans la section synthesize
@synthesize picker = _picker;

Cela ne devrait pas vous poser de problème après la première partie de cette série !

2) Mettre en place la Rate View

// Remplacez configureView par ce qui suit
- (void)configureView
{
    // Update the user interface for the detail item.
    self.rateView.notSelectedImage = [UIImage imageNamed:@"shockedface2_empty.png"];
    self.rateView.halfSelectedImage = [UIImage imageNamed:@"shockedface2_half.png"];
    self.rateView.fullSelectedImage = [UIImage imageNamed:@"shockedface2_full.png"];
    self.rateView.editable = YES;
    self.rateView.maxRating = 5;
    self.rateView.delegate = self; 
}

Dans la fonction configureView (qui est appelée à partir de la fonction viewDidLoad), nous mettons en place les propriétés de la vue de classement 5-étoiles RateView. Pour plus de détails sur son fonctionnement, vous pouvez consulter le tutoriel Créer une UIView personnalisée : Une vue d’appréciation sur 5 étoiles (en anglais).

3) Activer la rotation de l’interface

// Remplacez la clause return de la méthode shouldAutorotateToInterfaceOrientation par:
return YES;

Dans la méthode shouldAutorotateToInterfaceOrientation, on renvoie YES car notre interface est adaptée aux deux orientations après notre travail dans Interface Builder ! C’est cette ligne de code qui permet à l’application d’activer la rotation de l’interface en fonction des actions de l’utilisateur.

4) Configuration de l’état initial de l’interface graphique

// À la fin de la méthode configureView
if (self.detailItem) {
    self.titleField.text = self.detailItem.data.title;
    self.rateView.rating = self.detailItem.data.rating;    
    self.imageView.image = self.detailItem.fullImage;
}

Ici, nous assignons aux éléments graphiques les valeurs correspondantes à l’insecte qui a été sélectionné.

5) Gestion des vues de texte et de notation

- (IBAction)titleFieldTextChanged:(id)sender {
    self.detailItem.data.title = self.titleField.text;
}
 
#pragma mark UITextFieldDelegate
 
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    [textField resignFirstResponder];
    return YES;
}
 
#pragma mark RateViewDelegate
 
- (void)rateView:(RateView *)rateView ratingDidChange:(float)rating {
    self.detailItem.data.rating = rating;
}

Nous avons configuré titleFieldValueChanged pour être appelée à chaque fois que l’utilisateur change la valeur du champ de texte, nous mettons donc à jour le modèle de données dans cette action.

textFieldShouldReturn est appelée à chaque fois que l’utilisateur appuie sur la touche « Retour » du clavier. Nous appelons alors la méthode resignFirstResponder de l’objet représentant le champ de texte pour que le clavier disparaisse à l’exécution de cette action. resignFirstResponder est une fonction qui indique au champ de texte qu’il ne doit plus être l’élément d’interface sur lequel nous sommes focalisés.

La méthode rateView:ratingIsChanged est automatiquement appelée lorsque l’utilisateur choisit une nouvelle note car nous avons assigné cette classe comme delegate de l’élément RateView. Lorsque cette action se produit, nous mettons à jour les données dans notre modèle.

Si vous vous demandez à quoi servent les lignes qui commencent par #pragma mark, il s’agit simplement de marqueurs lus par XCode pour générer des séparateurs et libellés dans la liste des fonctions, pour une meilleure organisation :

Utilisation des pragma mark pour organizer son code

6) Afficher l’image picker et utiliser son résultat

- (IBAction)addPictureTapped:(id)sender {
    if (self.picker == nil) {   
        self.picker = [[UIImagePickerController alloc] init];
        self.picker.delegate = self;
        self.picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        self.picker.allowsEditing = NO;    
    } 
    [self.navigationController presentModalViewController:_picker animated:YES];    
}
 
#pragma mark UIImagePickerControllerDelegate
 
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    [self dismissModalViewControllerAnimated:YES];
}
 
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {    
 
    [self dismissModalViewControllerAnimated:YES];
 
    UIImage *fullImage = (UIImage *) [info objectForKey:UIImagePickerControllerOriginalImage]; 
    UIImage *thumbImage = [fullImage imageByScalingAndCroppingForSize:CGSizeMake(44, 44)];
    self.detailItem.fullImage = fullImage;
    self.detailItem.thumbImage = thumbImage;
    self.imageView.image = fullImage;
}

Nous avons précédemment configuré un appel de la méthode addPictureTapped lorsque l’utilisateur appuie sur notre bouton invisible qui recouvre l’UIImageView. Ici, nous créons donc l’objet du système qui permet de sélectionner une image : UIImagePicker. Nous lui assignons la bibliothèque de photos de l’utilisateur comme source d’images (cela aurait pu être l’appareil photo à la place). Nous assignons la classe self comme delegate pour recevoir les messages en retour lorsque l’utilisateur a fini de choisir son image. Ensuite, nous affichons la vue de façon modale, c’est à dire recouvrant tout l’écran et nécessitant une action avant de revenir à notre interface.

Finalement, nous implémentons le traitement des callbacks de l’objet UIImagePicker, c’est à dire les fonctions de retour qui seront appelées en fin de sélection d’image ou d’abandon de sélection d’image. Dans les deux cas, nous faisons disparaître l’image picker, et si l’utilisateur a effectivement sélectionné une image, nous obtenons cette image en taille normale, créons une version réduite (à l’aide de la classe UIImageExtras que nous avons ajouté au projet tout à l’heure) et nous mettons à jour la vue et le modèle de données.

Et bien… je pense que vous en avez un peu assez d’écrire du code maintenant, non ? Pas de panique, nous avons quasiment fini. Il ne reste plus qu’à raccorder l’écran au reste de l’application !

Intégration de la Detail View

Cela devrait être très rapide. Selon que vous suiviez ce guide depuis le début ou à partir des fichiers fournis en téléchargement en fin de la première partie, il se peut que le travail soit même déjà fait. Cependant, il est intéressant d’apprendre comment fonctionne la création de liens entre écrans dans le storyboard.

Ouvrez le fichier MainStoryboard.storyboard. Les flèches entre les différents écrans s’appellent des Segues, nous allons créer la liaison entre la vue Master et Detail. Sélectionnez la cellule de la table view dans le Master View Controller. En maintenant la touche « Ctrl », glissez cette cellule jusqu’au Detail View Controller : un petit menu apparait pour choisir un type de liaison « Push, Modal, ou Custom ». Choisissez Push, la liaison est alors créée sous la forme d’une flèche comme l’image suivante le montre :

Connexion des ViewControllers avec un Segue

Maintenant, il reste à s’assurer que lors du passage d’un écran à l’autre, l’insecte sélectionné dans la table soit correctement passé au contrôleur de la vue de détail. Ouvrez MasterViewController.m et procédez aux changements suivants :

// Ajouter en haut du fichier
#import "DetailViewController.h"
 
// À la fin de viewWillAppear
[self.tableView reloadData];
 
// En fin de fichier
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    DetailViewController *detailController =segue.destinationViewController;
    ScaryBugDoc *bug = [self.bugs objectAtIndex:self.tableView.indexPathForSelectedRow.row];
    detailController.detailItem = bug;
}

Premièrement, remarquez que dans la méthode viewWillAppear, nous rechargeons les données dans la table. Nous le faisons parce que l’utilisateur a la possibilité de modifier les données dans la vue de détail, il faut donc gérer l’éventualité d’un changement de données lors du retour vers la vue principale. La façon la plus simple de gérer ce cas est de recharger la table entière.

Ensuite, pourquoi avons nous créé une méthode prepareForSegue ? Dans l’éditeur de storyboard, nous avons créé une liaison entre les deux vues, la liaison s’appelle un Segue (un mot d’origine italienne signifiant « transition »). Juste avant l’exécution de la transition, iOS appelle automatiquement la méthode prepareForSegue pour nous donner une chance de passer les informations utiles à la vue de destination. Ici, nous passons l’objet représentant l’insecte qui a été sélectionné dans la table view.

Et voilà, on a fini ! Vous pouvez compiler et lancer le projet, si tout va bien, vous êtes maintenant capables de faire apparaître la vue de détail en sélectionnant un insecte, changer le nom, l’image ou la note des insectes, et même tourner l’iPhone dans les différentes orientations !

Exemple de Detail View Controller

Et maintenant ?

Voici un fichier du projet avec tout le code que nous avons fait jusqu’à présent dans cette série.

Merci de m’indiquer si quelque chose vous semble confus ou si vous aimeriez qu’une partie soit un peu plus développée.

Dans la suite de cette série, nous verrons comment ajouter et supprimer des insectes, ajouter une icône et image de lancement au projet, et comment gérer correctement les opérations dont l’exécution prend tu temps !

Ray Wenderlich

Ray is an indie software developer currently focusing on iPhone and iPad development, and the administrator of this site. He’s the founder of a small iPhone development studio called Razeware, and is passionate both about making apps and teaching others the techniques to make them.

When Ray’s not programming, he’s probably playing video games, role playing games, or board games.

Commentaires

1 Comment

  • hello
    please i'm cameroonian and i don't speak english well. so i will speak french.
    s'il vous plait j'ai du mal tlcharger le logiciel xcode voulez vous pour ceux qui ont le set up me l'envoyer dans mon adresse email que voici:mailevrard21@gmail.com
    itachi

Other Items of Interest

Newsletter mensuelle de Ray

Inscrivez-vous pour recevoir une newsletter mensuelle avec mes liens de développement favoris et recevez un très long tutoriel gratuit comme bonus!

Annoncez avec nous!

Nos livres

Notre Equipe

Tutorial Team

  • Corinne Krych

... 51 en tout!

Update Team

  • Zouhair Mahieddine

... 15 en tout!

Equipe de rédaction

  • Alexis Gallagher

... 23 en tout!

Code Team

  • Orta Therox

... 3 en tout!

Équipe de traduction

  • Jesus Guerra

... 33 en tout!

Spécialistes en la matière

  • Richard Casey

... 4 en tout!