Premiers pas avec les Storyboards d’iOS 5, Partie 2

Ray Wenderlich

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

ervez-vous quelques storyboards !

Note de Ray : Ceci est le second tutoriel de la série iOS 5 Feast (le banquet festif iOS 5) ! Ce guide est un aperçu gratuit de notre livre « iOS 5 By Tutorials ». Ce chapitre a été écrit par Matthijs Hollemans, également auteur de la série iOS Apprentice. Régalez-vous !

Cet article a été écrit par le membre de l’équipe “iOS Tutorial” Matthijs Hollemans, un designer et développeur iOS expérimenté.
Si vous voulez en savoir plus sur la nouvelle fonctionnalité de storyboarding d’iOS 5, vous êtes au bon endroit !
Dans la première partie, nous avons couvert les bases de l’utilisation de l’éditeur de Storyboard pour créer et connecter différents view controllers. Nous avons également vu comment créer une table view avec des cellules personnalisées directement dans l’éditeur de storyboard.
Dans cette seconde partie, nous allons voir les transitions « Segues », les cellules statiques de table view, l’écran d’ajout de données et un écran de sélection de données !

Nous commençons là où nous avions laissé le projet dans la première partie, je vous conseille donc de procéder aux étapes de celle-ci si ce n’est déjà fait.

Bien, plongeons directement dans une fonctionnalité importante des storyboards !

Je vous présente les Segues

Il est temps d’ajouter quelques view controllers à notre storyboard. Nous allons créer un écran qui permet d’ajouter des joueurs à notre application.
Glissez un « Bar Button Item » (élément de barre de boutons) du côté droit de la barre de navigation de l’écran Players. Dans l’inspecteur d’attributs, changez son identifiant (Identifier) à la valeur « Add » afin de lui donner l’apparence d’un bouton standard « + ». Lorsque l’on appuiera sur ce bouton, nous allons faire apparaître un écran modal en « pop-up » dans lequel on pourra saisir les détails du nouveau joueur.
Glissez un nouveau contrôleur dans le canevas, de type « Table View Controller », à droite de l’écran Players. N’oubliez pas que vous pouvez double-cliquer sur le canevas pour ajuster le niveau de zoom si vous avez besoin de place pour positionner vos éléments.

Gardez ce nouveau Table View Controller sélectionné et intégrez-le dans un Navigation Controller comme nous l’avions fait dans la première partie (si vous avez oublié, cela se fait par l’action du menu « Editor > Embed In > Navigation Controller »).

Maintenant, voici comment on relie nos éléments : Sélectionnez le bouton « + » que nous venons d’ajouter, et faites un Ctrl-Glissé vers le nouveau Navigation Controller :

Creation d’un Segue dans l’éditeur de storyboard

Quand vous lâchez le bouton de la souris, un petit menu apparaît en pop-up :

Choix du type de Segue - push, modal, ou custom

Parmi les trois choix (Push qui signifie « Pousser », Modal ou Custom qui signifie « Personnalisé »), choisissez Modal. Une nouvelle flèche apparaît entre l’écran Players et le Navigation Controller :

Affichage du nouveau Segue dans l’éditeur de storyboard

Ce type de connexion est appelé Segue (prononcé en anglais « sèguouè » il s’agit d’un terme peu utilisé qui signifie « enchaînement ». On continuera à utiliser le mot Segue pour bien l’associer à l’élément précis d’Xcode). Le Segue représente une transition d’un écran à un autre. Les connexions que nous avions jusqu’à présent étaient des relations d’appartenance entre des view controllers conteneur-contenu. Un Segue, à l’inverse, modifie ce qui est à l’écran. Il est déclenché par un bouton, un tap sur une cellule de table view, ou autre type d’action.

Ce qui est bien avec l’utilisation de Segues est que l’on n’a plus besoin d’écrire le code de présentation du nouvel écran ou même de relier les boutons aux IBActions. Ce que nous venons de faire, le Ctrl-Glissé à partir du bouton de la barre de navigation vers le nouvel écran, est suffisant pour créer la transition de façon concrète (Si votre contrôle avait déjà une connexion à un IBAction, alors le Segue l’emporte dessus).

Lancez l’application et appuyez sur le bouton « + ». Une nouvelle table view glisse à l’écran !

L’application avec le Segue modal

On parle plus souvent de fenêtre modale pour une boîte de dialogue qui nécessite une réponse pour pouvoir retourner à l’écran précédant son apparition. Ici, avec un Segue modal, un nouvel écran recouvre complètement le précédent. L’utilisateur ne peut interagir avec le précédent avant d’avoir refermé le nouvel écran. Plus tard, nous verrons les Segues « Push » qui poussent les nouveaux écran dans la pile de navigation.

Notre nouvel écran n’est pas encore très utile… on ne peut même pas le fermer pour revenir au précédent !

Le Segue n’a qu’un sens : de l’écran Players vers ce nouvel écran. Pour revenir, il nous faut utiliser le design pattern « Delegate ». Pour cela, nous devons donner à cette scène sa propre classe. Ajoutez une nouvelle sous-classe de UITableViewController au projet et nommez la PlayerDetailsViewController.
Pour la relier au storyboard, retournez dans l’éditeur de storyboard, sélectionnez la scène du nouveau contrôleur de table view et dans l‘inspecteur d’identité (Identity), assignez-lui la classe PlayerDetailsViewController (champ Class de l’inspecteur). J’oublie souvent cette étape, attention à ne pas faire comme moi !
Tant que nous y sommes, modifiez le titre de l’écran, en double-cliquant sur sa barre de navigation, nommez-le « Add Player ». Dans l’inspecteur d’attributs, changez la propriété Identifier des boutons de la barre de navigation : choisissez « Cancel » (Annuler) pour le bouton de gauche et « Done » (Terminé) pour le bouton de droite.

Barre de navigation avec son nouveau titre

Ensuite, dans le fichier PlayerDetailsViewController.h, remplacez le contenu par ce qui suit :

@class PlayerDetailsViewController;
 
@protocol PlayerDetailsViewControllerDelegate <NSObject>
- (void)playerDetailsViewControllerDidCancel:
  (PlayerDetailsViewController *)controller;
- (void)playerDetailsViewControllerDidSave:
  (PlayerDetailsViewController *)controller;
@end
 
@interface PlayerDetailsViewController : UITableViewController
 
@property (nonatomic, weak) id <PlayerDetailsViewControllerDelegate> delegate;
 
- (IBAction)cancel:(id)sender;
- (IBAction)done:(id)sender;
 
@end

Cela définit un nouveau protocole de délégation (PlayerDetailsViewControllerDelegate) que l’on utilisera pour communiquer avec l’écran Players lorsque l’utilisateur appuiera sur Cancel ou Done.

Retournez à l’éditeur de storyboard pour relier le bouton Cancel et Done à leurs méthodes respectives. Pour ce faire, vous pouvez faire un Ctrl-glissé à partir du bouton et vers le view controller en choisissant l’action correspondante dans le menu qui s’ouvre en pop-up :

Connexion de l’action d’un bouton à la méthode dans le view controller

À la fin du fichier PlayerDetailsViewController.m, ajoutez ces deux méthodes :

- (IBAction)cancel:(id)sender
{
	[self.delegate playerDetailsViewControllerDidCancel:self];
}
- (IBAction)done:(id)sender
{
	[self.delegate playerDetailsViewControllerDidSave:self];
}

Ce sont les méthodes associées aux actions des deux boutons de la barre de navigation. Pour le moment, tout ce qu’elles font est de notifier à la classe se trouvant dans la propriété delegate que l’action vient d’être déclenchée. C’est à la classe qui est delegate que revient la responsabilité de fermer cet écran. Cette façon de structurer les actions et les responsabilités n’est pas obligatoire mais c’est une pratique qui me semble bonne.

Remarquez qu’il est coutumier d’inclure, parmi les paramètres des méthodes de délégation, un paramètre contenant une référence de l’objet en question (comme premier ou seul paramètre). Dans notre cas, il s’agit de l’objet PlayerDetailsViewController. Ainsi, l’objet delegate sait toujours quel autre objet lui envoie un message.
N’oubliez pas d’ajouter la ligne synthesize pour la propriété delegate :

@synthesize delegate;

Maintenant que nous avons créé le protocole, il nous faut une classe qui implémente ce dernier. Il devrait sembler évident de le faire dans la classe PlayersViewController, puisque cette dernière est le view controller qui présente l’écran « Add Player ». Ajoutez les lignes suivantes au fichier PlayersViewController.h :

#import "PlayerDetailsViewController.h"
 
@interface PlayersViewController : UITableViewController <PlayerDetailsViewControllerDelegate>

…et celles-ci, à la fin du fichier PlayersViewController.m :

#pragma mark - PlayerDetailsViewControllerDelegate
 
- (void)playerDetailsViewControllerDidCancel:
  (PlayerDetailsViewController *)controller
{
	[self dismissViewControllerAnimated:YES completion:nil];
}
 
- (void)playerDetailsViewControllerDidSave:
  (PlayerDetailsViewController *)controller
{
	[self dismissViewControllerAnimated:YES completion:nil];
}

Pour l’instant, tout ce que font ces méthodes est de fermer l’écran « Add Player » qui a été présenté. Plus tard, nous y ajouterons des choses plus intéressantes.

La méthode dismissViewControllerAnimated:completion: est nouvelle dans iOS 5. Vous avez peut-être déjà utilisé dismissModalViewControllerAnimated: auparavant. Cette dernière fonctionne toujours mais à partir de maintenant, on préfèrera utiliser la première (elle permet d’ailleurs d’exécuter du code après la disparition de l’écran, ce que ne permettait pas son ancien équivalent).

Il ne reste plus qu’une chose à ajouter pour que l’ensemble soit cohérent et fonctionne : l’écran Players doit dire à PlayerDetailsViewController qu’il est maintenant son delegate (son responsable). Malheureusement, on ne peut pas simplement le faire dans l’éditeur de storyboard en traçant une ligne entre les deux… il nous faut écrire du code. Pour passer des données entre des view controllers lors de l’exécution d’un Segue, il faut le faire dans une méthode nommée prepareForSegue dans le view controller d’où part le Segue.

Ajoutez la méthode suivante au fichier PlayersViewController :

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
	if ([segue.identifier isEqualToString:@"AddPlayer"])
	{
		UINavigationController *navigationController = 
          segue.destinationViewController;
		PlayerDetailsViewController 
          *playerDetailsViewController = 
            [[navigationController viewControllers] 
              objectAtIndex:0];
		playerDetailsViewController.delegate = self;
	}
}

La méthode prepareForSegue est invoquée lorsqu’un Segue va démarrer. Le nouveau view controller a été chargé par le storyboard mais il n’est pas encore visible, c’est donc le moment où on a l’opportunité de lui envoyer des données (on n’appelle pas nous-mêmes la méthode prepareForSegue, c’est un message envoyé par UIKit pour nous dire qu’un Segue vient d’être déclenché).

Comme la destination de notre Segue est un Navigation Controller, il nous faut quelques lignes de code pour aller chercher le view controller qu’il contient et auquel on s’intéresse pour lui assigner la propriété delegate.
Lancez l’application, appuyez sur le bouton « + », et essayez de fermer l’écran « Add Player »… ça ne marche toujours pas !
C’est parce que nous n’avons pas donné d’identifiant au Segue. Le code de la méthode prepareForSegue vérifie un identifiant de Segue. Il est recommandé par Apple de toujours vérifier l’identifiant du Segue parce que la méthode prepareForSegue est appelée pour tout Segue de notre view controller, ce test permet de distinguer de quel Segue il s’agit (et même si nous n’en avons qu’un actuellement, ce sera plus simple d’en ajouter un si l’on suit déjà cette recommandation).
Pour résoudre ce problème, allez dans l’éditeur de storyboard et cliquez sur le Segue entre l’écran Players et le Navigation Controller. Notez que le bouton de la barre de navigation est mis en évidence, pour montrer quel contrôle est rattaché à ce Segue.
Dans l’inspecteur d’attributs, assignez l’identifiant « AddPlayer » :

Identifiant d’un Segue

Si vous lancez à nouveau l’application, tout fonctionne et nous pouvons maintenant fermer le nouvel écran en appuyant sur les boutons « Cancel » et « Done », et ainsi revenir à la liste des joueurs sur l’écran Players.
Si vous lancez à nouveau l’application, tout fonctionne et nous pouvons maintenant fermer le nouvel écran en appuyant sur les boutons « Cancel » et « Done », et ainsi revenir à la liste des joueurs sur l’écran Players.
Remarque : Il est tout à fait possible d’appeler dismissViewControllerAnimated:completion: depuis l’écran modal. Le fait de procéder comme ce tutoriel avec un protocole de délégation n’est pas du tout obligatoire. Je préfère opérer de cette manière mais si vous souhaitez que l’écran modal se ferme seul, libre à vous. Dans ce cas, il faut que vous connaissiez un changement qui a eu lieu avec iOS 5 : Si vous avez déjà utilisé [self.parentViewController dismissModalViewControllerAnimated:YES] pour fermer un écran, il n’est pas garanti que cela fonctionne encore. À la place de self.parentViewController, appelez la méthode sur self ou sur self.presentingViewController (qui est une nouvelle propriété, introduite par iOS 5).
Au fait, l’inspecteur d’attributs d’un Segue possède un champ « Transition ». Vous pouvez choisir différentes animations :

Choix d’un style de transition d’un Segue

Testez-les pour voir celles que vous préférez, mais ne changez pas le « Style » : ce dernier doit rester « Modal » pour notre écran — tout autre choix ferait planter l’application !
Nous utiliserons encore le design pattern Delegate au fil de ce tutoriel. Voici une check-list pratique pour la mise en place d’une connexion entre deux scènes :

  1. Création d’un Segue à partir d’un bouton (ou autre contrôle) de la scène initiale vers la scène de destination (si le nouvel écran est modal, la scène de destination sera fréquemment un Navigation Controller)
  2. Attribution d’un Identifier au Segue (il doit être unique pour la scène d’où part le Segue ; on peut donc utiliser plusieurs fois un même identifiant sur un grand storyboard)
  3. Création du protocole de délégation pour la scène de destination
  4. Appel des méthodes de délégation à partir des boutons Cancel et Done, et à tout endroit dans lequel votre scène de destination a besoin de communiquer avec la scène initiale
  5. Implémentation de ce méthodes dans la scène initiale. Ces méthodes devraient logiquement fermer l’écran lorsque les boutons Cancel ou Done sont actionnés
  6. Implémentation de prepareForSegue dans le view controller de la scène initiale pour y mettre la ligne de code « destination.delegate = self »

L’utilisation de « Delegates » est utile parce qu’il n’y a pas de Segue pour le retour. Quand un Segue se déclenche, il crée une nouvelle instance du view controller de destination. Il est possible d’ajouter un Segue dans l’autre sens dans l’éditeur de storyboard, mais cela ne produirait pas le résultat que vous espérez.

Par exemple, si vous faites un nouveau Segue à partir du bouton Cancel vers l’écran Players, il faut bien comprendre que cela ne fermerait pas l’écran « Add Player » en appuyant sur le bouton
Cancel
, mais cela créerait une nouvelle instance de l’écran « Players » qui viendrait s’afficher par dessus. Vous débuteriez là un cycle potentiellement infini, qui ne pourrait s’arrêter que lorsque l’appareil n’a plus de mémoire.

Retenez : Les Segues ne vont que dans un sens, ils sont utilisés pour ouvrir de nouveaux écrans. Pour revenir aux écrans précédents, il faut utiliser la méthode « dismiss » du view controller ou la méthode « pop » de la pile de navigation, on fera souvent cela à partir d’une classe responsable (le delegate du design pattern du même nom). Le Segue est utilisé par l’écran initial, le view controller de destination n’a même pas conscience d’avoir été créé par un Segue.

Cellules statiques

Lorsque nous aurons terminé, l’écran « Add Player » ressemblera à ceci :

L’écran Add Player une fois terminé

C’est bien sûr une table view de style groupé (groupes), mais la nouveauté est que nous n’avons pas besoin de créer les données sources de cette table dans le code. Nous allons les assigner directement dans l’éditeur de storyboard… pas la peine d’écrire de méthode cellForRowAtIndexPath pour cette table. La nouvelle fonctionnalité qui rend ceci possible s’appelle « Static cells » (cellules statiques).

Sélectionnez la table view dans l’écran Add Player, puis dans l’inspecteur d’attributs, attribuez la valeur « Static Cells » au champ Content (qui signifie « Contenu »). Plus bas, choisissez 2 sections ainsi que le style « Grouped ».

Configuration d’une table avec des cellules statiques

Lorsque vous changez la valeur du nombre de sections, l’éditeur clone la section existante. Il est également possible d’aboutir au même résultat en dupliquant la section dans la panneau de gauche (dans la hiérarchie des objets de la scène).
Notre écran n’aura qu’une ligne par section, vous pouvez donc sélectionner les cellules superflues et les effacer.
Sélectionnez la section la plus en haut. Dans l’inspecteur d’attributs, donnez au champ Header (en-tête) la valeur « Player Name » (Nom du joueur).

Mise en place d’un en-tête de section dans use table

Glissez un nouveau champ de texte (Text Field) dans la cellule de cette section. Supprimez sa bordure de sorte à ce que l’on ne distingue pas où le champ de texte commence et se termine. Donnez-lui la police de caractères « System 17 » (champ Font) et décochez la case « Adjust to Fit » (qui indique, lorsqu’elle est cochée, au champ de texte d’ajuster sa taille aux dimensions de son contenu).
Nous allons créer une connexion (un outlet) à ce champ de texte dans la classe PlayerDetailsViewController, en utilisant la fonctionnalité d’Xcode nommée « Assistant Editor ». Ouvrez l’éditeur assistant à l’aide du bouton de la barre d’outils (à droite, avec une icône de costume-nœud-papillon… certains y voient un visage Alien !). L’éditeur assistant devrait s’ouvrir automatiquement sur le fichier PlayerDetailsViewController.h.
Sélectionnez le champ de texte et faites un Ctrl-Glissé vers le fichier .h :

Ctrl-glissé pour connecter un outlet dans l’éditor assistant

Lâchez le bouton de la souris, un menu apparait en pop-up :

Pop-up de connexion d’un UITextField à un outlet

Nommez l’outlet nameTextField. Après que vous ayez validé par le bouton Connect, Xcode ajoute la propriété suivante au fichier PlayerDetailsViewController.h :

@property (strong, nonatomic) IBOutlet UITextField *nameTextField;

Xcode a également automatiquement ajouté la ligne « @synthesize » correspondante à cette propriété dans le fichier PlayerDetailsViewController.m, ainsi qu’ajouté le code nécessaire dans la méthode viewDidUnload.

C’est exactement le type de choses que je vous avais dit de ne pas faire pour les cellules prototypes, mais c’est tout à fait correct avec les cellules statiques. En effet, il n’y aura jamais qu’une seule instance de chaque cellule statique, contrairement aux cellules prototype. On peut donc connecter les sous-vues à des outlets de notre view controller.

Pour la seconde section da la table, choisissez le style de cellule statique « Right Detail » (détail à droite). On obtient alors une cellule standard que l’on peut personnaliser. Remplacez le texte du libellé de gauche par « Game » et donnez à la cellule un indicateur de déploiement (disclosure indicator accessory, dans l’inspecteur d’attributs). Créez un outlet pour le libellé de droite (celui qui s’appelle « Detail ») et nommez-le detailLabel. Les libellés de cette cellule sont de simples objets UILabel.

La mise en page de notre écran « Add Player » est complète et doit ressembler à ceci :

Design final de l’écran Add Player

Lorsque vous utilisez des cellules statiques, le view controller de votre table n’a pas besoin de source de données. Comme nous avons utilisé un modèle d’Xcode pour la classe PlayerDetailsViewController, il y a dans le code des emplacements prévus pour notre source de données… prenons donc une minute pour les supprimer du code. Effacez les lignes entre les marqueurs suivants :

	#pragma mark - Table view data source

et :

	#pragma mark - Table view delegate

Xcode devrait maintenant arrêter de nous afficher les avertissements qui étaient apparus depuis la création de cette classe.

Lancez l’application et vérifiez notre nouvel écran et ses cellules statiques. Tout cela sans écrire de code… nous en avons même supprimé !

Nous ne pouvons cependant pas complètement éviter d’écrire du code. Lorsque vous avez ajouté le champ de texte à la première cellule, vous avez probablement remarqué que le champ de texte ne prend pas toute la place de la cellule. Si l’utilisateur touche la cellule dans cet espace de marge, rien ne se produira, ce qui est étrange pour lui car il ne peut pas voir que le champ de texte n’occupe pas tout l’espace. Pour éviter cela, nous allons lui autoriser de toucher n’importe où dans la cellule pour éditer le champ de texte en affichant le clavier. C’est assez facile à faire, remplacez simplement la méthode tableView:didSelectRowAtIndexPath: par la suivante :

	- (void)tableView:(UITableView *)tableView
	didSelectRowAtIndexPath:(NSIndexPath *)indexPath
	{
	if (indexPath.section == 0)
	[self.nameTextField becomeFirstResponder];
	}

Cela indique tout simplement que si l’utilisateur touche la première cellule du tableau, nous activons le champ de texte (comme il n’y a qu’une seule cellule dans la première section, on fait le test sur la section toute entière). Cela va automatiquement afficher le clavier à l’écran. Ceci n’est qu’un petit ajustement qui peut sembler mineur, mais cela évitera de potentielles frustrations à l’utilisateur.

Vous devriez aussi changer le style de sélection de la cellule : choisissez « None » à la place de « Blue » dans l’inspecteur d’attributs, de sorte à éviter que la cellule devienne bleue si l’utilisateur touche la marge de la cellule, à côté du champ de texte.

Bien, la présentation de l’écran est finie, maintenant il nous faut le faire fonctionner.

L’écran Add Player au travail

Pour le moment, nous allons ignorer la ligne Game et nous occuper uniquement du champ de texte afin de permettre à l’utilisateur d’y saisir le nom du joueur.

Lorsque l’utilisateur appuie sur le bouton Cancel, l’écran doit se fermer et les données saisies dans le champ de texte doivent être perdues. Le fonctionnement actuel de l’application est donc déjà correct et cohérent dans ce cas. Le delegate (l’écran Players) reçoit le message « did cancel » et ferme le view controller.

Lorsque l’utilisateur appuie sur le bouton Done, par contre, nous devons créer un nouvel objet Player représentant le nouveau joueur, et lui remplir ses propriétés. Ensuite, nous devons dire au delegate que nous avons créé un nouvel objet Player pour qu’il puisse mettre à jour l’affichage de son écran.

Donc, dans PlayerDetailsViewController.m, remplacez la méthode « done » par :

	- (IBAction)done:(id)sender
	{
	Player *player = [[Player alloc] init];
	player.name = self.nameTextField.text;
	player.game = @"Chess";
	player.rating = 1;
	[self.delegate playerDetailsViewController:self
	didAddPlayer:player];
	}

Cela requiert un import pour l’objet Player :

	#import "Player.h"

La méthode « done » crée maintenant une nouvelle instance d’objet Player et l’envoie au delegate. Le protocole de délégation ne possède pas encore cette méthode, ajoutons-la au fichier PlayerDetailsViewController.h :

	@class Player;
 
	@protocol PlayerDetailsViewControllerDelegate <NSObject>
		- (void)playerDetailsViewControllerDidCancel:
		(PlayerDetailsViewController *)controller;
		- (void)playerDetailsViewController:
		(PlayerDetailsViewController *)controller
		didAddPlayer:(Player *)player;
		@end

La déclaration de méthode « didSave » a disparu. À la place, nous avons maintenant « didAddPlayer ».

La dernière chose à faire est d’ajouter l’implémentation de cette méthode dans PlayersViewController.m :

 
	- (void)playerDetailsViewController:
	(PlayerDetailsViewController *)controller
	didAddPlayer:(Player *)player
	{
	[self.players addObject:player];
	NSIndexPath *indexPath =
	[NSIndexPath indexPathForRow:[self.players count] - 1
	inSection:0];
	[self.tableView insertRowsAtIndexPaths:
	[NSArray arrayWithObject:indexPath]
	withRowAnimation:UITableViewRowAnimationAutomatic];
	[self dismissViewControllerAnimated:YES completion:nil];
	}

Premièrement, cela ajoute le nouvel objet Player à la collection de joueurs. Ensuite, cela indique à la table view qu’une ligne a été ajoutée (à la fin), car la vue de la table et sa source de données doivent toujours être synchronisées. Nous aurions pu simplement utiliser [self.tableView reloadData] mais il me semble plus subtil d’ajouter la nouvelle rangée avec une animation. UITableViewRowAnimationAutomatic est une nouvelle constante d’iOS 5 qui choisit automatiquement l’animation adaptée, selon l’endroit où l’on insère la nouvelle ligne… pratique !

Essayez l’application, vous devriez maintenant pouvoir ajouter de nouveaux joueurs à la liste !

Si vous vous posez des questions sur l’impact qu’a l’utilisation de storyboards sur les performances de l’application, sachez que le chargement complet du storyboard n’est pas un problème. Le storyboard ne crée pas les instances de tous les view controllers dès le départ mais uniquement du view controller initial. Comme notre premier view controller est un contrôleur de barre d’onglets (Tab Bar Controller), les deux view controllers qu’il contient sont également chargés (la scène Players et la scène du second onglet).

Les autres view controllers ne sont instanciés que lorsqu’un Segue dont ils sont la destination est déclenché. Lorsque vous fermez un view controller, son espace mémoire est désalloué. Seuls les view controllers en utilisation active restent donc en mémoire, comme si on utilisait des fichiers nibs séparés.

Voyons cela en pratique. Ajoutez les méthodes suivantes au fichier PlayerDetailsViewController.m :

	- (id)initWithCoder:(NSCoder *)aDecoder
	{
	if ((self = [super initWithCoder:aDecoder]))
	{
	NSLog(@"init PlayerDetailsViewController");
	}
	return self;
	}
	- (void)dealloc
	{
	NSLog(@"dealloc PlayerDetailsViewController");
	}

Nous surchargeons les méthodes initWithCoder et dealloc pour y écrire un message dans les logs de la zone de Debug. Lancez à nouveau l’application et ouvrez l’écran Add Player. Vous devriez voir dans les logs le moment où ce view controller est instancié. Lorsque vous fermez l’écran « Add Player » par le bouton Cancel ou Done, vous devriez également voir dans les logs le message écrit depuis la méthode dealloc. Si vous ouvrez à nouveau l’écran, un nouveau message est écrit depuis la méthode initWithCoder. Cela montre bien que les view controllers sont chargés à la demande, tout comme on le faisait précédemment à iOS 5 par l’utilisation de fichiers nibs.

Avant de passer à la suite, voici quelques informations à propos des cellules statiques : elles ne fonctionnent que dans un UITableViewController. L’éditeur de storyboard vous laisse libre d’en créer à l’intérieur d’un objet Table View dans un UIViewController classique, mais cela ne fonctionnera pas lors de l’exécution de l’application. L’explication réside dans le fait que l’objet UITableViewController fournit des éléments supplémentaires s’occupant de la source de données correspondante à vos cellules statiques. Xcode vous empêche même de compiler un projet si vous essayez, avec ce message d’erreur : « Illegal Configuration: Static table views are only valid when embedded in UITableViewController instances » (qui signifie « Configuration interdite : les tables statiques ne sont valides que si elles sont incluses à une instance de UITableViewController ».

Les cellules prototypes, par contre, fonctionnent parfaitement dans un view controller classique. Cependant, on ne peut travailler avec dans Interface Builder. Pour le moment, si vous voulez utiliser des cellules prototypes ou statiques, il faut utiliser un storyboard.

On pourrait imaginer que vous souhaitiez créer une table qui possède à la fois des cellules statiques et des cellules dynamiques : ceci n’est pas très bien supporté par le SDK. Si c’est quelque chose dont vous avez besoin, consultez ce sujet de discussion pour une solution possible (en anglais).

Remarque : Si vous construisez une table qui possède plus de cellules statiques que ne peut en contenir un écran, les gestes de défilement au trackpad ou à la souris fonctionnent dans l’éditeur de storyboard pour faire défiler uniquement les cellules de la table.

Suivez ce lien pour accéder à la fin de ce tutoriel.

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

0 Comment

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!

Votez pour le prochain Tutoriel!!

Chaque semaine, nous alternons entre les sujets de tutoriels Jeux et Non-Gaming. Cette semaine : Non-Gaming!

    Loading ... Loading ...

Last week's winner: Best iOS Animations in 2014. [Read Now]!

Suggérer un tutoriel - Résultats précédents

Hang Out With Us!

Every month, we have a free live Tech Talk - come hang out with us!


Coming up in October: Xcode 6 Tips and Tricks!

Sign Up - October

Nos livres

Notre Equipe

Tutorial Team

  • Matt Galloway

... 49 en tout!

Update Team

  • Andy Pereira
  • Ray Fix

... 15 en tout!

Equipe de rédaction

  • John Clem

... 22 en tout!

Code Team

  • Orta Therox

... 3 en tout!

Équipe de traduction

  • Victor Grushevskiy
  • Jiyeon Seo

... 32 en tout!

Spécialistes en la matière

  • Richard Casey

... 4 en tout!