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

Ray Wenderlich

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

Servez-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é.

Les Storyboards sont une nouvelle fonctionnalité intéressante d’iOS 5 qui vous permettra d’économiser beaucoup de temps lors de la conception de l’interface graphique de vos applications. Pour vous montrer ce que sont les storyboards, je vais laisser parler l’image : Voici le storyboard que nous allons construire dans ce tutoriel :

Le storyboard complet que nous allons créer au cours de cet article

Sans même savoir exactement ce que va faire cette application, vous pouvez déjà voir quels écrans elle possède et leurs relations. C’est possible grâce à l’utilisation des storyboards.

Si vous avez une application avec beaucoup d’écrans différents, alors les storyboards peuvent aider à réduire la quantité de code technique et répétitif à écrire pour aller d’un écran à l’autre. Au lieu d’utiliser un fichier *.nib séparé pour chaque view controller, votre application utilise un unique fichier storyboard qui contient la conception graphique de tous les contrôleurs ainsi que les relations entre eux.

Les storyboards présentent un certain nombre d’avantages sur les fichiers nib :

  • Avec les storyboards, vous avez une meilleure vue d’ensemble de tous les écrans de l’application et des interconnexions entre eux. Il est plus facile d’effectuer un suivi de chaque élément parce que tout est réuni dans un fichier.
  • Les storyboards décrivent les transitions entre les écrans. Les transitions sont nommées « Segues » et sont créées par une simple manipulation de Ctrl-Glissé (un déplacement de souris en maintenant la touche Ctrl enfoncée) d’un contrôleur à un autre. À l’aide des Segues, moins de code doit être écrit pour l’interface de l’application.
  • Il est bien plus facile de travailler avec des TableViews avec les storyboards grâce aux nouvelles fonctionnalités de cellules prototypes et statiques. On peut maintenant concevoir presque complètement une table view dans l’éditeur de storyboards, cela réduit également la quantité de code que l’on a à écrire.

Tout n’est cependant pas parfait évidemment, et les storyboards ont également des limitations. L’éditeur de storyboard n’est pas encore aussi puissant qu’Interface Builder, quelques fonctionnalités de ce dernier sont absentes. Aussi, il est préférable de posséder un grand écran, surtout pour travailler sur une application à destination de l’iPad !

Si vous êtes du genre à détester Interface Builder et que vous préférez concevoir vos interfaces graphiques par programmation, les storyboards ne vous plairont probablement pas. Personnellement, je préfère écrire le moins de code possible — surtout le code d’interface utilisateur ! – et cet outil est donc bienvenu dans mon arsenal.

Vous pouvez continuer à utiliser les fichiers nib avec iOS 5 et Xcode 4.2. L’utilisation d’Interface Builder n’est pas désapprouvée depuis l’apparition des storyboards. Si vous souhaitez continuer à utiliser les fichiers nib, libre à vous, mais sachez qu’il est tout à fait possible de combiner l’utilisation de storyboards et de fichiers nib : pas besoin de se restreindre à l’un ou l’autre.

Dans ce tutoriel, nous allons passer en revue ce que l’on peut faire avec les storyboards. L’application que nous allons concevoir n’est pas des plus utiles mais elle nous permet de montrer comment utiliser les storyboards pour les tâches les plus courantes.

Premiers pas

Lancez Xcode et créez un nouveau projet. Nous allons utiliser le modèle Single View Application (Application à vue unique) comme point de départ , nous créeront ensuite le reste de l’interface à partir de là.

Options de modèle Xcode

Remplissez les options du modèle comme suit :

  • Product Name : Ratings
  • Company Identifier : l’identifiant que vous utilisez pour vos applications, en notation inverse de domaine
  • Class Prefix : laissez ce champ vide
  • Device Family : iPhone
  • Use Storyboard : cochez cette case
  • Use Automatic Reference Counting : cochez cette case (pour utiliser ARC, outil de gestion de la mémoire)
  • Include Unit Tests : ne cochez pas cette case

Une fois qu’Xcode a créé le projet, la fenêtre principale devrait ressembler à ceci :

Xcode après la création du projet

Notre nouveau projet consiste en deux classes, AppDelegate et ViewController, ainsi que la star de ce tutoriel : j’ai nommé le fichier MainStoryboard.storyboard. Remarquez qu’il n’y a aucun fichier .xib dans le projet, pas même MainWindow.xib.

Jetons un œil à ce storyboard. Sélectionnez le fichier MainStoryboard.storyboard dans le Project Navigator pour ouvrir l’éditeur de Storyboard :

Éditeur de Storyboard

L’éditeur de Storyboard ressemble beaucoup à Interface Builder. Vous pouvez glisser des nouveaux contrôles à partir de la bibliothèque d’objets (dans le coin en bas à droite) vers votre contrôleur pour concevoir sa présentation. La différente est que l’éditeur de storyboards ne se contente pas de contenir un seul contrôleur de l’application mais il les contient tous.

La terminologie officielle dans le storyboard est une « scène », mais une scène n’est rien d’autre qu’un View Controller. Précédemment, vous utilisiez un fichier nib différent pour chaque scène / contrôleur de vue, maintenant ils sont tous combinés dans un unique storyboard.

Sur l’iPhone, une seule scène est visible à la fois, mais sur iPad, vous pouvez avoir plusieurs scènes visibles en même temps. Par exemple, les panneaux Master et Detail d’une Split-view ou le contenu d’une fenêtre popup.

Pour vous familiariser avec le fonctionnement de l’éditeur, glissez quelques contrôles dans le contrôleur vide :

Glisser des contrôles à partir de la bibliothèque d’objets

La barre verticale située à gauche contient la hiérarchie des objets du document :

Hierarchie du document

Dans Interface Builder, cette zone liste les éléments du fichier nib alors que dans l’éditeur de storyboard, elle contient tous les view controllers. Actuellement, nous n’en avons qu’un, mais nous en ajouterons bientôt d’autres.

Il y a une version miniature de cette hiérarchie du document en bas de chaque scène, dans une zone appelée « Dock » :

Le Dock title=

Le Dock montre les objets de niveau le plus haut de la scène. Chaque scène possède au moins un objet First Responder et un objet View Controller, mais elle peut potentiellement avoir d’autres objets à ce niveau. Le Dock est pratique pour créer des connexions. Si vous avez besoin de connecter quelque chose avec un contrôleur, vous pouvez glisser son icône vers le Dock du contrôleur.

Remarque : Vous n’utiliserez probablement pas beaucoup le First Responder. Il s’agit d’un objet proxy qui se réfère à l’objet de la scène qui possède le statut de first responder (par exemple, un champ de texte possède ce statut lorsque le clavier est montré pour y écrire). Cet objet existait également dans Interface Builder et vous n’y avez probablement jamais touché. Un exemple d’utilisation est de connecter un événement Touch Up Inside d’un bouton au sélecteur cut: de l’objet First Responder. Ainsi, lorsqu’un champ de texte est actif (il est le first responder, le fait d’appuyer sur le bouton déclenchera la méthode cut: qui coupera le texte sélectionné dans le presse-papier.

Lancez l’application et elle devrait ressembler à ce que nous avons conçu dans l’éditeur :

L’application et ses objets

Si vous aviez déjà travaillé avec une application basée sur des fichiers nib, vous aviez un fichier MainWindow.xib. Ce fichier nib contenait l’objet UIWindow de niveau principal, une référence à l’App Delegate et un ou plusieurs contrôleurs. Cependant, lorsque vous placez l’interface utilisateur de votre application dans un storyboard, ce fichier MainWindow.xib n’existe plus.

Au revoir, MainWindow.xib

Alors comment le storyboard est-il chargé dans l’application s’il n’y a plus de fichier MainWindow.xib ?

Voyons voir dans la classe responsable de l’application : Ouvrez AppDelegate.h et vous devriez voir ceci :

#import <UIKit/UIKit.h>
 
@interface AppDelegate : UIResponder <UIApplicationDelegate>
 
@property (strong, nonatomic) UIWindow *window;
 
@end

Il est nécessaire pour utiliser les storyboards que l’application delegate hérite de UIResponder (auparavant, elle héritait directement de NSObject) et qu’elle possède une propriété UIWindow (qui, contrairement à iOS 4, n’est pas un IBOutlet).

Si vous regardez dans AppDelegate.m, vous verrez qu’il n’y a absolument rien de concret à l’intérieur, toutes les méthodes sont pratiquement vides. Même la méthode application:didFinishLaunchingWithOptions: se contente de renvoyer YES. Précédemment, elle contenait le code qui ajoutait la vue du View Controller principal à la fenêtre, ou assignait la propriété rootViewController de la fenêtre. Rien de ceci ne se passe ici.

Le secret se trouve dans le fichier Info.plist. Sélectionnez le fichier Ratings-Info.plist qui se trouve dans le groupe « Supporting Files », vous verrez ceci :

Le nom du fichier du storyboard est précisé dans Info.plist

Dans les projets basés sur des fichiers nib, il y avait une clé nommée NSMainNibFile dans le fichier Info.plist (ou « Main nib file base name »). Cette clé indiquait à UIApplication de charger le fichier MainWindow.xib et de le raccorder à l’application. Notre nouveau fichier Info.plist n’a plus besoin de cette valeur.

À la place, les applications utilisant un storyboard possèdent la clé UIMainStoryboardFile (ou « Main storyboard file base name ») pour spécifier le nom du fichier de storyboard qui doit être chargé lorsque l’application est lancée. Lorsque cette valeur est présente, UIApplication s’occupera de charger le fichier MainStoryboard.storyboard et créera automatiquement une instance du premier View Controller de ce storyboard, puis le placera sa vue dans un nouvel objet UIWindow. Aucune programmation n’est nécessaire pour cela.

On peut également voir le réglage du fichier Info.plist dans l’écran « Target Summary » d’Xcode :

Réglage du fichier storyboard dans l’écran Target Summary

Il y a ici une nouvelle section « iPhone/iPod Deployment Info » qui permet de choisir entre un fichier de lancement de type storyboard ou nib.

Par souci d’exhaustivité, voyons enfin le fichier main.m pour voir ce qu’il contient :

#import <UIKit/UIKit.h>
 
#import "AppDelegate.h"
 
int main(int argc, char *argv[])
{
        @autoreleasepool {
                return UIApplicationMain(argc, argv, nil,
                        NSStringFromClass([AppDelegate class]));
    }
}

Précédemment, le dernier paramètre pour UIApplicationMain() était nil mais maintenant il contient NSStringFromClass([AppDelegate class]).

La différence majeure avec le fonctionnement précédent est que l’application delegate ne fait pas partie du storyboard. Comme il n’est pas chargé à partir d’un fichier nib ou storyboard, nous avons besoin de dire à UIApplicationMain le nom de notre classe qui joue le rôle d’application delegate. Ainsi, l’application sera en mesure de le trouver et l’instancier.

Placer des écrans dans des onglets

Notre application Ratings a une interface en deux écrans accessibles par des onglets en bas de l’écran. Avec les storyboards, il est très facile de créer ce type d’interface.

Retournez au fichier MainStoryboard.storyboard, et glissez un objet « Tab Bar Controller » à partir de la bibliothèque d’objets vers le canevas. Vous aurez peut-être besoin d’agrandir la fenêtre parce que ce contrôleur est accompagné de deux autres view controllers et il faut de la place pour manœuvrer.

Ajout d’un contrôleur d’onglets au Storyboard

Le nouveau Tab Bar Controller est pré-configuré avec deux view controllers, un pour chaque onglet. UITabBarController est une sorte de conteneur de view controllers parce qu’il contient un ou plusieurs autres view controllers. D’autres conteneurs classiques sont les Navigation Controller et Split View Controller, nous les verrons en détail plus tard. Une nouvelle fonctionnalité d’iOS 5 est l’ajout d’une nouvelle API pour écrire ses propres conteneurs — et dans ce livre, nous avons un tutoriel sur le sujet !

La relation d’appartenance est représentée dans l’éditeur de storyboard par la flèche entre le Tab Bar Controller et le contrôleur qu’il contient :

Une flèche de relation dans l’éditeur de Storyboard

Remarque : Pour déplacer le Tab Bar Controller et ses contrôleurs attachés simultanément, il faut les sélectionner en groupe en les ajoutant un par un à la sélection par un Cmd-clic. Les scènes sélectionnées sont surlignées en bleu et peuvent être déplacées ensemble.

Glissez un libellé (label) dans le premier view controller et assignez-lui le texte « First Tab ». Faites de même dans le second view controller et nommez-le « Second Tab ». Ceci va nous permettre de voir ce qu’il se passe lorsque l’on passe d’un onglet à l’autre.

Remarque : Vous ne pouvez pas glisser de nouveaux éléments dans les scènes lorsque le niveau de zoom est minimal. Il est nécessaire de revenir au niveau de zoom normal avant d’ajouter un objet.

Sélectionnez le Tab Bar Controller et allez dans le panneau « Attributes Inspector ». Cochez la case intitulée « Is Initial View Controller ».

Attribut Is Initial View Controller

Dans le canevas, la flèche qui précédemment pointait vers notre premier contrôleur est maintenant placée devant le Tab Bar Controller :

Cette flèche indique le contrôleur initial du storyboard

Cela signifie que lorsque vous lancerez l’application, la classe UIApplication fera de notre Tab Bar Controller l’écran principal initial.

Le storyboard ne peut posséder qu’un unique view controller qui possède cette propriété, c’est le point d’entrée du storyboard.

Lancez l’application pour vérifier que cela fonctionne. L’application a maintenant une barre d’onglet et vous pouvez passer d’un écran à l’autre en l’actionnant :

L’app avec la barre d’onglets

Xcode possède en fait un modèle d’application nommé « Tabbed Application template » que nous aurions pu utiliser pour en arriver au même point, mais ces quelques étapes étaient l’occasion de décrire le fonctionnement de base des storyboards.

Vous pouvez supprimer le view controller qui avait été initialement créé par le modèle d’application, nous ne nous en servirons plus. Le storyboard ne contient maintenant plus que notre barre d’onglets et ses deux scènes associées.

Pour information, si vous connectez plus de cinq scènes à un Tab Bar Controller, une section « More » est automatiquement créée pour gérer les écrans qui ne rentrent pas dans la barre. Pratique !

Ajout d’un Table View Controller

Les deux scènes actuellement attachées au Tab Bar Controller sont des UIViewControllers « simples ». Je souhaite remplacer la scène du premier onglet par une liste, un UITableViewController.

Cliquez sur ce premier view controller pour le sélectionner et effacez-le. À partir de la bibliothèque d’objets (en bas à droite), glissez un nouveau Table View Controller dans le canevas à l’emplacement où se trouvait la scène précédente :

Ajout d’un table view controller au Storyboard

Une fois le Table View Controller positionné et sélectionné, choisissez le menu « Editor > Embed In > Navigation Controller ». Cette action ajoute un nouveau View Controller au canevas :

Intégration dans un navigation controller

Il est également possible d’obtenir le même résultat en choisissant un Navigation Controller dans la bibliothèque d’objets, mais cette méthode est plus pratique.

Comme le Navigation Controller est également un conteneur, il a une flèche représentant sa relation au Table View Controller. Vous pouvez aussi voir les relations dans la hiérarchie des objets de niveau principal, dans le panneau de gauche :

Relations de view controllers

Remarquez que le fait d’avoir intégré le Table View Controller à un Navigation Controller lui a donné une barre de navigation. L’éditeur de storyboard l’affiche automatiquement parce qu’il sait que cette scène sera affichée à l’intérieur du cadre d’un Navigation Controller. Il ne s’agit pas d’un vrai objet de type UINavitationBar mais d’une simulation de l’éditeur.

Si vous regardez l’inspecteur d’attributs pour le Table View Controller (dans le panneau de droite), vous verrez une section nommée « Simulated Metrics » :

Simulated metrics dans l’éditeur de Storyboard

La valeur “Inferred” est sélectionnée par défaut et laisse l’éditeur choisir la situation à simuler : l’éditeur affichera une barre de navigation pour un contrôleur se trouvant lié à un Navigation Controller et fera de même pour la barre d’onglets. On peut passer outre ce réglage en choisissant les autres valeurs, mais il est important de savoir qu’il ne s’agit que d’une valeur simulée dans l’éditeur, pour s’aider à concevoir l’interface des écrans. Ces valeurs simulées ne sont pas utilisées par l’application en fonctionnement, elle ne peuvent que servir d’aide visuelle.

Connectons ces nouvelles scènes au Tab Bar Controller. Faites un Ctrl-glissé en partant du Tab Bar Controller jusqu’au Navigation Controller :

Connexion des scenes dans le storyboard

Au moment de lâcher le clic, un petit menu apparaît en popup :

Creation d’un Segue de type Relation

Choisissez la valeur « Relationship – viewControllers » signifiant que vous souhaitez créer un Segue de type « Relation entre contrôleurs ». La flèche représentant la relation s’affiche :

Affichage de la relationship

Le Tab Bar Controller a deux relations de ce type : une pour chaque onglet. Le Navigation Controller a lui aussi une telle relation avec le Table View Controller. Il existe cependant d’autres types de liens que nous verrons plus tard.

Lorsque nous avons créé cette nouvelle connexion, un nouvel onglet s’est ajouté à la barre d’onglet du Tab Bar Controller, nommé « Item ». On souhaite que cette scène soit en première position dans les onglets, il nous suffit de glisser les onglets pour changer leur ordre :

Ré-arrangement des onglets

Lancez l’application pour l’essayer. Le premier onglet contient le contrôleur de Table View dans un Navigation Controller.

L’application et sa Table View

Avant d’ajouter de réelles fonctionnalités à notre application, préparons un peu le storyboard. Je souhaite nommer le premier onglet « Players » et le second « Gestures ». Ceci ne se fait pas dans le Tab Bar Controller mais dans les contrôleurs qui sont rattachés à ces onglets.

Dès que vous connectez un contrôleur au Tab Bar Controller, un élément de la barre d’onglet lui est associé (Tab Bar Item). C’est cet objet qu’il faut utiliser pour configurer le titre et l’image de l’onglet.

Sélectionnez cet élément Tab Bar Item situé à l’intérieur du Navigation COntroller et dans le panneau d’attributs à droite (Attributes Inspector), assignez la valeur « Players » au champ « Title » (Titre) :

Changement du titre d’un Tab Bar Item

Faites de même avec le contrôleur du second onglet, nommez-le « Gestures ».

Nous devrions également mettre des images dans ces onglets. Les ressources de ce tutoriel contiennent un dossier nommé Images. Ajoutez ce dossier au projet. Dans l’inspecteur d’attributs du Tab Bar Item de l’onglet « Players », choisissez l’image “Players.png”. Vous l’avez deviné, il faut faire la même chose avec l’onglet « Gestures » et l’image “Gestures.png”.

D’une façon comparable, un contrôleur à l’intérieur d’un Navigation Controller a un objet de type Navigation Item qui lui est associé et qui doit être utilisé pour configurer la barre de navigation. Sélectionnez l’objet Navigation Item pour le Table View Controller et changez le titre dans l’inspecteur d’attributs (Valeur « Players » pour le champ « Title »).

Plus pratique, il est possible de double-cliquer sur la barre de navigation et changer le titre directement ici. (Il faut pour cela double-cliquer sur la barre de navigation simulée par l’éditeur de storyboard dans le Table View Controller, mais pas sur la “vraie” barre de navigation qu’est l’objet Navigation Bar du Navigation Controller.)

Changement du titre du Navigation Item

Lancez l’application et admirez notre nouvel écran, sans même avoir écrit la moindre ligne de code !

App with the final tabs

Cellules prototypes

Peut-être avez-vous remarqué que depuis que nous avons ajouté le Table View Controller, Xcode affiche un avertissement :

Avertissement d’Xcode : Prototype cells must have reuse identifiers

Le message d’avertissement, « Unsupported Configuration: Prototype table cells must have reuse identifiers » signifie « Configuration non supportée : Les cellules prototypes de la table doivent avoir un identifiant de réutilisation ». Lorsque l’on ajoute une Table View à un storyboard, elle est prévue pour utiliser des cellules prototypes par défaut, mais nous n’avons pas configuré cela correctement, cet avertissement est donc logique.

Les cellules prototypes sont l’un des avantages intéressant que les storyboards offrent par rapport aux classiques fichiers nib. Auparavant, si vous souhaitiez utiliser une table avec des cellules au design personnalisé, il vous fallait ajouter les sous-vues par programme ou créer un fichier nib spécifique pour la cellule et le charger par du code. C’est toujours possible, mais les cellules prototypes rendent les choses plus simples. Maintenant, il est possible de concevoir notre cellule type directement dans l’éditeur de storyboard.

Le Table View Controller vient avec une cellule prototype vide. Cliquez sur cette cellule pour la sélectionner et dans l’inspecteur d’attributs, assignez-lui le style « Subtitle » (Sous-titre). Cela change immédiatement l’apparence de la cellule pour comporter deux libellés. Si vous avez déjà utilisé des table view précédemment et créé vos propres cellules à la main, vous devriez reconnaître le style UITableViewCellStyleSubtitle. Avec les cellules prototypes, vous pouvez choisir un style pré-existant comme nous venons de le faire, ou créer une présentation personnalisée (ce que nous ferons bientôt).

Création d’une cellule prototype

Pour l’attribut « Accessory », choisissez la valeur « Disclosure Indicator » (vous constaterez alors le changement de l’icône à droite de la cellule), puis saisissez comme identifiant Reuse Identifier l’expression « PlayerCell ». L’avertissement d’Xcode n’aura plus lieu d’être une fois ceci fait. Toutes les cellules prototypes restent de simples objets UITableViewCell et devraient donc déjà avoir un identifiant de réutilisation, mais Xcode s’assure simplement que nous n’oublions pas d’assigner le nôtre (en tout cas pour ceux qui font attention aux avertissements).

Lancez l’application et… rien n’a changé. Ce n’est pas une surprise, il nous faut encore créer la source de données pour la table afin de lui donner quelque chose à afficher.

Ajoutez un nouveau fichier au projet. Choisissez le modèle « UIViewController subclass template ». L’option « With XIB for user interface » doit être décochée (elle signifie que l’on souhaite ajouter un fichier XIB pour l’interface, mais nous allons faire celle-ci dans notre storyboard : Pas de nib pour aujourd’hui !).

Création d’un view controller aver le modèle de table view controller

Retournez à l’éditeur de storyboard et sélectionnez le Table View Controller. Dans l’inspecteur « Identity », assignez la classe PlayersViewController (dans le champ Class). C’est une étape essentielle pour relier une scène du storyboard à votre propre sous-classe de view controller. Ne l’oubliez pas ou votre classe ne sera tout simplement pas utilisée !

Assigner le nom de la classe dans l’inspecteur Identity

À partir de cet instant, lorsque l’on lance l’application, ce view controller du storyboard est une instance de notre classe PlayersViewController.

Ajoutez une propriété de type mutable array (tableau modifiable) à PlayersViewController.h

#import <UIKit/UIKit.h>
 
@interface PlayersViewController : UITableViewController
 
@property (nonatomic, strong) NSMutableArray *players;
 
@end

Ce tableau contiendra les données principales de notre modèle de données, des objets Player. Créons cette classe Player maintenant. Ajoutez un nouveau fichier au projet en utilisant le modèle « Objective-C class ». Nommez la classe « Player », sous-classe de NSObject.

Modifiez Player.h pour obtenir ceci :

@interface Player : NSObject
 
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *game;
@property (nonatomic, assign) int rating;
 
@end

…et le fichier Player.m de façon suivante :

#import "Player.h"
 
@implementation Player
 
@synthesize name;
@synthesize game;
@synthesize rating;
 
@end

Il n’y a rien de très particulier ici. Player est simplement un objet pour stocker ces trois propriétés : le nom du joueur (name), le jeu auquel il joue (game), et une note (rating, de 1 à 5 étoiles).

Nous créerons le tableau et quelques objets Player de test dans la classe App Delegate, et nous assignerons ce tableau à la propriété players de la classe PlayersViewController.

Dans AppDelegate.m, ajoutez une ligne #import pour les classes Player et PlayersViewController en haut du fichier, et ajoutez une nouvelle variable d’instance nommée players :

 
#import "AppDelegate.h"
#import "Player.h"
#import "PlayersViewController.h"
 
@implementation AppDelegate {
        NSMutableArray *players;
}
 
// Reste du fichier...

Puis changez la méthode didFinishLaunchingWithOptions comme suit :

 
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
        players = [NSMutableArray arrayWithCapacity:20];
        Player *player = [[Player alloc] init];
        player.name = @"Bill Evans";
        player.game = @"Tic-Tac-Toe";
        player.rating = 4;
        [players addObject:player];
        player = [[Player alloc] init];
        player.name = @"Oscar Peterson";
        player.game = @"Spin the Bottle";
        player.rating = 5;
        [players addObject:player];
        player = [[Player alloc] init];
        player.name = @"Dave Brubeck";
        player.game = @"Texas Hold’em Poker";
        player.rating = 2;
        [players addObject:player];
        UITabBarController *tabBarController =
     (UITabBarController *)self.window.rootViewController;
        UINavigationController *navigationController =
     [[tabBarController viewControllers] objectAtIndex:0];
        PlayersViewController *playersViewController =
     [[navigationController viewControllers] objectAtIndex:0];
        playersViewController.players = players;
    return YES;
}

Cela sert tout simplement à créer quelques objets Player et les placer dans un tableau. Mais à la fin, nous faisons ceci :

UITabBarController *tabBarController = (UITabBarController *)
  self.window.rootViewController;
UINavigationController *navigationController =
  [[tabBarController viewControllers] objectAtIndex:0];
PlayersViewController *playersViewController =
  [[navigationController viewControllers] objectAtIndex:0];
playersViewController.players = players;

Euh… qu’est ce que c’est ? Et bien nous souhaitons placer notre tableau de players dans la propriété de PlayersViewController pour que ce dernier l’utilise comme source de données. Mais la classe AppDelegate ne connait rien de PlayersViewController pour l’instant, alors il nous faut la retrouver à partir de la racine du storyboard… c’est ce que nous faisons ici.

Ceci est l’une des limites des storyboards que je trouve ennuyeuse. Avec Interface Builder, nous avions toujours une référence vers l’AppDelegate dans MainWindow.xib et nous pouvions faire des connexions à partir des view controllers vers des outlets (propriétés d’accès) de l’AppDelegate. C’est dommage, mais nous pouvons toujours obtenir ces références par quelques lignes de code.

UITabBarController *tabBarController = (UITabBarController *)
  self.window.rootViewController;

Nous savons que le contrôleur initial du storyboard est un Tab Bar Controller, alors nous allons le chercher en appelant le contrôleur racine (rootViewController) de la fenêtre (self.window).

L’objet PlayersViewController est dans un navigation controller dans le premier onglet de ce UITabBarController, nous commençons donc par chercher l’objet UINavigationController :

UINavigationController *navigationController = [[tabBarController
  viewControllers] objectAtIndex:0];

Enfin, on obtient l’objet PlayersViewController que nous cherchions en demandant le contrôleur racine du UINavigationController :

PlayersViewController *playersViewController =
  [[navigationController viewControllers] objectAtIndex:0];

Malheureusement, UINavigationController n’a pas de propriété rootViewController, nous devons donc le faire en accédant au tableau viewControllers. Il y a une propriété topViewController mais elle pointe vers le contrôleur le plus élevé de la pile et nous recherchons le plus bas… pour l’instant (l’application vient à peine de se lancer) ce sont les mêmes, mais d’une manière générale ce n’est pas forcément le cas : ne prenons pas de mauvaises habitudes.

Maintenant que l’objet PlayersViewController possède le tableau d’objets Player, nous pouvons modifier cette classe pour l’utiliser comme source de données.

Ouvrez le fichier PlayersViewController.m et modifiez les méthodes de source de données de table view comme ceci :

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
        return 1;
}
 
- (NSInteger)tableView:(UITableView *)tableView
  numberOfRowsInSection:(NSInteger)section
{
        return [self.players count];
}

Les choses sérieuses se passent dans la méthode cellForRowAtIndexPath. La version initiale de cette méthode, issue du modèle d’Xcode, est celle-ci :

- (UITableViewCell *)tableView:(UITableView *)tableView
  cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
 
    UITableViewCell *cell = [tableView
      dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc]
          initWithStyle:UITableViewCellStyleDefault
          reuseIdentifier:CellIdentifier];
    }
 
    // Configure the cell...
    return cell;
}

C’est comme cela que l’on a toujours écrit le code d’une table view… et bien plus maintenant ! Remplacez cette méthode par la suivante :

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
        UITableViewCell *cell = [tableView
      dequeueReusableCellWithIdentifier:@"PlayerCell"];
        Player *player = [self.players objectAtIndex:indexPath.row];
        cell.textLabel.text = player.name;
        cell.detailTextLabel.text = player.game;
    return cell;
}

C’est beaucoup plus simple ! La seule chose à faire pour obtenir une cellule est :

UITableViewCell *cell = [tableView
  dequeueReusableCellWithIdentifier:@"PlayerCell"];

S’il n’y a aucune cellule à recycler, iOS se charge de créer une copie de la cellule prototype pour vous la renvoyer. Tout ce qu’il y a à faire est de fournir un identifiant de réutilisation (reuse identifier) assigné à la cellule prototype dans l’éditeur de storyboard (dans notre cas « PlayerCell »). N’oubliez donc pas cet identifiant lorsque vous essaierez de reproduire ce fonctionnement.

Comme cette classe ne connait pas notre objet Player pour le moment, il nous faut ajouter un #import en haut du fichier :

#import "Player.h"

Et nous devons ajouter la ligne synthesize pour notre propriété players si nous travaillons avec Xcode 4.3.x ou inférieur. (C’était le cas lors de l’écriture initiale de ce tutoriel)

@synthesize players;

Nous pouvons lancer l’application maintenant, et la table view contient enfin quelques données :

Des données dans la table view

Remarque : Dans cette application, nous n’utilisons qu’un seul prototype de cellule, mais si vous avez besoin d’une table avec plusieurs types de cellules différents, vous pouvez simplement ajouter des cellules prototypes dans le storyboard. Vous pouvez pour cela dupliquer la cellule existante ou incrémenter la valeur de l’attribut « Prototype Cells » de la table. Prenez soin de donner un identifiant à chaque prototype.

Une ligne suffit pour utiliser ces nouveaux petits prototypes… Ça me semble une nouveauté bienvenue !

Suivez ce lien pour accéder à la fin de cette première partie.

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!

Hang Out With Us!

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


Coming up in September: iOS 8 App Extensions!

Sign Up - September

RWDevCon Conference?

We are considering having an official raywenderlich.com conference called RWDevCon in DC in early 2015.

The conference would be focused on high quality Swift/iOS 8 technical content, and connecting as a community.

Would this be something you'd be interested in?

    Loading ... Loading ...

Nos livres

Notre Equipe

Tutorial Team

  • Tim Mitra

... 50 en tout!

Update Team

  • Zouhair Mahieddine

... 14 en tout!

Equipe de rédaction

  • Ryan Nystrom

... 23 en tout!

Code Team

  • Orta Therox

... 3 en tout!

Équipe de traduction

  • Di Peng

... 33 en tout!

Spécialistes en la matière

  • Richard Casey

... 4 en tout!