Les onglets avec UITabBarController [Tutoriel iPhone n°6] [XCode 4]
Nouveau (avril 2011) : Ce tutoriel a été mis à jour et été testé pour XCode 4.
Si UINavigationController permet d’organiser les vues de façon hiérarchique et de permettre à l’utilisateur d’obtenir des détails sur un élément de son choix, il est souvent nécessaire de proposer plusieurs fonctions ou modes de recherche de manière parallèle. Citons par exemple l’application iPod qui permet de rechercher un morceau de musique par artiste, par album, par genre, etc. Cette navigation par onglets positionnés en bas de l’écran est gérée par une classe CocoaTouch : UITabBarController. Dans ce tutoriel, vous verrez comment articuler plusieurs vues à l’aide de UITabBarController et comment vous pourrez personnaliser l’apparence de ce dernier.
Créer deux UIViews à afficher
Pour commencer, ouvrez XCode et créez un projet de type « Window Based Application ».
Nous allons maintenant créer deux vues que nous enregistrerons par la suite dans le UITabBarController. Pour créer la première vue, choisissez « New File… » dans le menu « File » de XCode, puis choisissez le type UIViewController Subclass. N’oubliez pas de cocher la case « With XIB for user interface » pour que le fichier Interface Builder soit automatiquement créé. Appelez cette classe TabLabelViewController.
Ouvrez le fichier TabLabelViewController.xib et ajoutez un UILabel au centre présentant le texte de votre choix. Sauvegarder avant de continuer.
Pour la seconde vue, je vous propose quelque chose d’un peu plus sympa qu’un bête texte : nous allons afficher un logo de votre choix. Commençons d’abord par ajouter l’image dans le projet. Pour ce faire, localisez le fichier sur votre disque dur et faîtes le glisser dans la colonne de gauche de XCode, dans le répertoire de votre projet. N’oubliez pas de cocher la case « Copy items into destination group’s folder (if needed) » dans la fenêtre qui s’ouvre, pour que l’image soit dupliquée dans votre projet (et éviter de perdre vos petits par la suite).
Créons maintenant une nouvelle classe que nous appellerons TabImageViewController. A nouveau ouvrez le fichier .xib, et faîtes-y glisser, depuis la bibliothèque, un élément Image View, il doit occuper toute la place disponible dans la vue principale.
Dans la partie supérieure de la zone de droite, choisissez, si ce n’est pas le cas l’onglet « Attributes inspector » (matérialisé par un petit curseur). Dans le champ « Image », choisissez l’image que nous avons ajoutée précédemment. Avant de sauvegarder, modifier le mode de positionnement pour trouver celui qui correspondra le mieux à votre image.
Créer l’objet UITabBarController et insérer les deux vues
Nous avons maintenant deux objets ViewController. Il s’agit de les associer à un UITabBarController et ainsi naviguer entre les deux. Pour ce faire, ouvrez le fichier appelé xxxAppDelegate.h (où « xxx » est à remplacer par le nom de votre projet). Ajoutez-y la déclaration d’un nouvel objet UITabBarController.
@interface TabBarTutorialAppDelegate : NSObject <UIApplicationDelegate> { UITabBarController *tabBarController; }
Ouvrez le fichier xxxAppDelegate.m pour modifier l’implémentation. Dans d’en-tête du fichier, importez les deux vues que nous venons de créer.
#import "TabLabelViewController.h" #import "TabImageViewController.h"
Repérez à présent la méthode - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions. Cette méthode est appelée (comme son nom l’indique) dès que l’application a fini de se charger. Pour être très complet, la classe xxxAppDelegate est une classe qui vient en soutient de chaque application. Vous avez la possibilité d’y implémenter des méthodes qui seront utiles tout au long de la vie de l’application. Une traduction possible de « Delegate » est « Représentant » ce qui correspond bien à l’usage que nous avons des AppDelegate : ce sont les représentants de l’application ; nous leur apprenons à réagir convenablement quand il arrive quelque chose à l’application (démarrage, arrêt, mise en veille ou même problème de mémoire).
Mais je m’égare et philosophe sur les AppDelegate. Repérez donc cette méthode « didFinishLaunching » qui, pour le moment se charge d’afficher une fenêtre. Nous devons faire trois choses dans cette méthode :
- Instancier le UITabBarController
- Créer un TabLabelViewController et l’enregistrer dans le UITabBarController
- Créer un TabImageViewController et l’enregistrer
Pour enregistrer les vues dans le UITabBarController, nous utiliserons sa propriété viewControllers qui est en fait un tableau de vues.
Voici donc le code à implémenter.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. // Créer un tabBarViewController tabBarController = [[UITabBarController alloc] init]; // Créer une vue 1 et affecter TabLabelViewController *v1 = [[TabLabelViewController alloc] initWithNibName:@"TabLabelViewController" bundle:nil]; // Créer une vue image et affecter TabImageViewController *v2 = [[TabImageViewController alloc] initWithNibName:@"TabImageViewController" bundle:nil]; tabBarController.viewControllers = [NSArray arrayWithObjects:v1, v2, nil]; [v1 release]; [v2 release]; [self.window addSubview:tabBarController.view]; [self.window makeKeyAndVisible]; return YES; }
Notez qu’une fois les deux UIViewController créés et ajoutés dans le NSArray, nous leur passons un signal release : ils sont en effet retenus par le UITabBarController.
Vous pouvez compiler et faire un premier essai de votre application. Vous obtiendrez bien une barre d’onglets en bas de l’écran permettant de naviguer entre les deux vues.
Personnaliser l’apparence du UITabBarController
Il y a quand même un petit problème : les onglets sont vides ! Il devraient être associés à une image et à un intitulé, au minimum. Avant de commencer, il est nécessaire de bien comprendre le fonctionnement de UITabBarController : pour savoir ce qu’il doit afficher dans l’onglet correspondant à un ViewController, il va le lui demander ! C’est le ViewController qui définit son apparence dans la barre d’onglets. Ceci se fait à l’aide d’un objet UITabBarItem qui est enregistré dans la propriété tabBarItem du UIViewController.
Le UITabBarItem permet de préciser :
- le titre qui s’affiche en bas
- une image. Cette image sera au format PNG en noir et transparent. Les pixels noirs seront automatiquement colorés par iOS avec cet effet bleuté pour indiquer que l’onglet est actif. Taille 30px par 30px
- un tag : un nombre qui pourra être affichés sous forme d’une petite pastille rouge.
Pour le TabLabelViewController, nous allons créer une image PNG de notre cru (ici un petit crayon) et choisir le titre « Label ».
Pour ce faire, créez l’image avec votre logiciel préféré (on a qu’à dire GIMP) ou téléchargez-la en faisant un clic-droit sur l’image ci-dessus, et ajoutez-la au projet en le faisant glisser vers la colonne de gauche de XCode. Ouvrez le fichier TabLabelViewController.m, repérez la méthode initWithNibName, et complétez-la avec le code suivant :
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.tabBarItem = [[[UITabBarItem alloc] initWithTitle:@"Label" image:[UIImage imageNamed:@"crayonnoir.png"] tag:0] autorelease]; } return self; }
Pour le TabImageViewController, encore plus rapide, nous allons utiliser un élément standard du système. Il en existe quelques un : une étoile pour les favoris, un livre ouvert pour les favoris, des utilisateurs, un loupe pour la recherche… Nous allons utiliser UITabBarSystemItemFeatured qui est représenté par deux spots vers le haut. Cette fois, même plus besoin de choisir de titre : tout est fait automatiquement (et traduit).
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.tabBarItem = [[[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemFeatured tag:0] autorelease]; } return self; }
Attention cependant, l’usage des icônes UITabBarSystemItem est très encadré par Apple pour maintenir une cohérence de la signification de ces onglets dans tout le système. Référez vous au guide « Human Interface guidelines » pour l’utilisation de ces icônes.
Et voilà un bon aperçu de tout ce que vous pouvez faire avec UITabBarController. Une dernière chose quand même : vous pouvez ajouter autant de ViewControllers dans votre TabBar : s’il y en a trop pour tous les afficher en une seule fois, iOS proposera de lui-même un bouton « More » et permettra à l’utilisateur de paramétrer son affichage et choisir l’ordre des onglets. Vous trouverez ce fonctionnement dans l’application iPod, par exemple.
Ce tutoriel touche à sa fin, merci d’être arrivé jusqu’au bout
N’hésitez pas à réagir dans les commentaires, ni à poser vos questions : nous essaierons de vous répondre et de vous aider dans votre dev. pour iPhone !

Cette création par Tuto Mobile est mise à disposition selon les termes de la licence Creative Commons Paternité - Pas d'Utilisation Commerciale - Partage des Conditions Initiales à l'Identique 3.0 Unported.
Encore un peu de lecture :
-
Création dʼun SplashScreen animé [Tutoriel iPhone n°12] -
[Concours] Résultats du concours pour gagner 4 formation video2brain iPhone -
[Concours] Gagner 4 formations vidéos pour apprendre le développement iPhone















Merci pour ce super tuto, très clair et très utile.
Très utile merci :p
merci beaucoup pour ce tuto, on attend la suite avec impatience
!!!
Tutorial sympa en effet … mais attention à ne pas montrer le mauvais exemple !
. A titre d’exemple il faut faire :
Il y a des fuites mémoires dans cet exemple
self.tabBarItem = [[[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemFeatured tag:0] autorelease];
N’oublie pas de fournir le code de tout l’exemple également. Je n’ai pas vu le dealloc de ton AppDelegate mais j’espère qu’il ressemble à :
- (void) dealloc {
[tabBarController release];
[window release];
[super dealloc];
}
Bonne continuation !
Merci Cyril : tu as tout à fait raison, il manquait un autorelease pour éviter que ça fuite ! C’est maintenant corrigé. Par ailleurs, un point plus complet sur la gestion mémoire est normalement prévu dans un prochain tutoriel.
Super tutoriel, merci.
J’ai une petite question : nous avons vu comment naviguer soit avec une UINavigationController soit avec un UITabBarController, en les instanciant dans le delegate.
Mais comment gérer les deux à la fois comme dans l’application iPod par exemple ?
J’ai finalement trouvé la solution
Pour ceux que cela intéresse :
1/ J’ai déclaré le TabLabelViewController comme « delegate » (.h) :
@interface xxxViewController : UIViewController
2/ Dans IB, j’y ai ajouté une NavigationBar, et relié son « delegate » au « File’s Owner »
3/ On applique le tutoriel 5, mais dans la méthode viewDidLoad du TabLabelViewController
Ca marche nickel !! On navigue à la fois via la TabBar, et lorsque nous sommes dans le premier onglet, on navigue dans cette vue via la NavigationBar du haut, comme dans l’app. iPod.
@Eric : Merci d’avoir partagé ta solution !
@Eric : Merci pour ta solution, mais j’arrive pas a faire fonctionner chez moi… je suis nouveau dans la programmation iphone et j’ai peut-etre rate un etape??
Magnifique tuto !
Vraiment c’est très bien expliqué et j’ai bien fait plaisir à le suivre.
Merci beaucoup et svp plus de tuto pour iphone, je vois assez de tuts à coté d’andro.
merci !!
beau travail !
Hello,
Excellent tuto.
Je me mets doucement au développement iPhone après plusieurs années de développement Web. J’ai juste un petit soucis :
Tuto suivi avec XCode 4, ça change peut-être
Dans le résultat, j’obtiens deux onglets identiques. Certes, ils dirigent bien vers la vue 1 et la vue 2, mais ils sont identique, semblable à celui que je définis dans TabLabelViewController.m.
En gros, j’ai deux Onglets qui s’appellent Label avec sur tous les deux le crayon noir, et non pas un tab favoris à droite.
Par contre, le tab de droite renvoie bien vers ma seconde vue, et celui de gauche vers ma première.
Développement de l’application effectué pour iOS 4.3
Reflexe de développeur, Copier Coller trop rapide !
Je me cache, et si l’on met ensemble l’heure qu’il est et ma productivité, j’en déduis qu’il est grand temps de me coucher.
Merci à toi pour ce super tuto !
@Gaetan : Il faut que je reteste tous les projets avec XCode 4, à l’occasion, mais normalement il ne devrait pas y avoir de problème particulier. En tous cas merci pour tes encouragements !
Salut tout le monde !
Ce tutoriel a été mis à jour et testé avec XCode 4. J’en ai profité pour rajouter la possibilité de télécharger l’image du petit crayon ! Have fun !
Hello !
Je suis sous Xcode 4 et cela fait 4 fois que je suis le tuto à la lettre, sans alcool ni fatigue particulière et je rencontre des difficultés : au run, sur le simulateur, à part un écran blanc, je n’avais rien.
J’ai donc relu tout le code de AppDelegate h et m
Dans le h, on déclare window puis on fait le property.
@interface TabBarTutorialAppDelegate : NSObject {
UIWindow *window;
UITabBarController *tabBarController;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
Dans le m, le synthesize existe déjà :
@synthesize window=_window;
Or, on utilise window quand Xcode utilise _window
J’ai donc supprimé le « =_window » dans le synthesize, et j’ai bien mes deux vues avec le tab bar. Sauf que celui ci ne comporte pas d’icones…
Je cherche donc.
Voila, si ça peut aider des gens qui galèrent comme moi, ben c’est bien.
ok ok ok, je fatigue peut être un peu, c’est normal qu’ils soient vides, on nous dit comment les remplir dans la suite du tuto. Pardon.
Je profite de ce post d’excuses pour poser une question, nul part dans le tuto on nous demande de faire les property et synthesize, alors que dans d’autres, c’est demandé. Est-ce propre à XCode 4 ? Pas utile ?
Je les ai mis pour tabBarController :
dans le h : @property (nonatomic, retain) UITabBarController *tabBarController;
dans le m : @synthesize tabBarController;
et ceci ne change rien à l’exécution du prog…
Une explication ?
En tout cas, merci beaucoup, tout ceci fait apprendre vite et bien !
A
@aldahi : Pour ta question concernant l’utilité des propriétés.
Dans ce tutoriel, il n’est pas vraiment utile de faire une propriété avec le tabBarController pour une raison simple : ici, on n’instancie UITabBarController qu’à un seul endroit. La propriété c’est quand même fait pour que d’autres objets puissent l’utiliser. Comme dans notre exemple il n’y a nul autre objet, il n’y a donc pas d’intérêt particulier à créer une propriété.
Cela étant dit, faire une propriété te permettra d’aller plus loin avec ton appli si tu le souhaites.
Bonjour,
ton tuto es très bien, mais je voudrais le pousser le plus loin.
Est-il possible de auto-hider le UITabBarController?
J’ai essayé avec hidesBottomBarWhenPushed = YES mais rien ne se passe. Des idées?