Tu veux promouvoir ton application ici ? Ce service est gratuit pour le moment alors profites en !


Tutoriel n°7 : TabBar & Delegate — V2

Dans ce tutoriel nous allons apprendre à utiliser une architecture «Tab Bar» pour switcher entre deux vues :
• une vue pouvant afficher une page web
• une vue servant à la rédaction d’emails

Nous obtiendrons une petite application ressemblant à ceci :

http://www.ipup.fr/forum/userimages/Capture-d-ecran-2010-03-27-a-19.22.02.png



1) Le Tab Bar :

Xcode, dans le but de simplifier le travail des développeurs, nous permet de nous exempter de tout un travail de mise en place de l’architecture et de pouvoir créer une application contenant déjà un «Tab Bar».

Néanmoins, dans certains cas il nous sera préférable de créer nous même les bases d’une application de ce type. Nous verrons donc un peu plus tard comment, pour des applications plus complexes, recréer un «Tab Bar» complètement en code (c.f. Tutoriel n°13).

Créons donc une «Tab Bar Application» et nommons la «iPuPMail».

http://www.ipup.fr/forum/userimages/Capture-d-ecran-2010-02-19-a-19.24.12.png





Mais qu’est ce qu’un «Tab Bar» ?

En effet, avant de commencer il est important de comprendre à quoi sert une telle architecture.

Un «Tab Bar» est un élément d’interface utilisateur permettant de passer rapidement et très simplement d’une vue à une autre dans une application.

D’ailleurs nous pouvons d’ores et déjà compiler et exécuter l’application (Pomme+R)  pour mieux nous rendre compte de ce qu’il en est réellement.




En démarrant Interface Builder via le fichier MainWindow.xib nous pouvons noter que la vue rattachée au second item de la barre est définie dans le fichier SecondView.nib. Toutes les vues doivent donc être reliée à un item (ou élément) du TabBar. Il nous serait d’ailleurs très aisé de rajouter une troisième vue en ajoutant un élément dans le «Tab Bar Controller» et en créant un troisième fichier nib - ThirdView.xib par exemple.

http://www.ipup.fr/forum/userimages/Capture-d-ecran-2010-02-19-a-19.48.49.png



Pour cette application Xcode nous fournit déjà tout le squelette nécessaire.


2) Affichage d’une page Web (UIWebView) :

Maintenant que nous sommes sûr que notre squelette est en place il ne nous reste plus qu’à commencer.

Pour cela attardons nous un peu sur le fichier MainWindow.xib afin de définir les éléments de notre première vue qui affichera une page web. Pour cela, plaçons sur cette première vue un élément de type «WebView».

http://www.ipup.fr/forum/userimages/Capture-d-ecran-2010-03-27-a-16.28.07.png



C’en est tout pour le moment avec Interface Builder, revenons donc à Xcode.

Comme d’habitude il faut déclarer nos éléments d’interfaces dans notre ViewController. Donc dans le fichier «FirstViewController.h» :

Ici nous déclarons l’objet de type WebView qui correspondra à celui que nous venons de placer dans Interface Builder. Le préfixe IBOutlet spécifie que cet élément doit être visible dans Interface Builder afin de pouvoir le relier .


@interface FirstViewController : UIViewController {
    IBOutlet UIWebView *webView;
}

Passons maintenant à l’implémentation du code source. Pour simplifier chaque étape est détaillée :


// Implement viewDidLoad to do additional setup after loading the view.
- (void)viewDidLoad {
    [super viewDidLoad];
    
    //Création d'un string contenant l'adress URL de la page web
    NSString *adresseUrl = @"http://www.ipup.fr";
        
    //Creation d'un objet de type URL contennant l'adresse contenue dans le String adresseUrl
    NSURL *url = [NSURL URLWithString:adresseUrl];
        
    //L'objet de type NSURLRequest est initialisée avec notre objet url
    NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
        
    //Charge la requête dans la UIWebView. Celle ci affichera alors le contenu de l'url
    [webView loadRequest:requestObj];
}

Voilà comme nous l’avons vu précédemment il ne faut pas oublier de relier dans Interface Builder notre objet «webView» à son élément.

Notre première vue affiche donc maintenant la page d'accueil de notre site préféré !

3) Envoi d’un mail :

Passons maintenant à notre deuxième vue (SecondView.xib) qui permettra d’envoyer des mails directement dans notre application.

Tout d'abord nous devons créer un deuxième ViewController que nous nommerons SecondViewController. En effet, le principe "Un ViewController - Une View" est une bonne habitude à prendre car elle permet d'architecturer le projet de manière plus propre.

Une fois les fichiers créés, nous devons relier le second item du TabBar à notre nouveau ViewController (MainWindow.xib puis sélectionner le second item) :

http://www.ipup.fr/forum/userimages/Capture-d-ecran-2010-03-27-a-18.19.06.png



Passons maintenant à la définition de la vue sous Interface Builder.

Pour cela nous devons tout d’abord placer deux «Text Fields» (qui contiendront respectivement l’adresse et l’objet), un «Text View» (pour le message), un bouton (pour envoyer notre prose) et quelques labels :

http://www.ipup.fr/forum/userimages/Capture-d-ecran-2010-03-27-a-17.57.31.png



Après avoir créé un second ViewController (SecondViewController) et installé nos éléments graphiques, nous devons maintenant rajouter les déclarations de nos éléments dans le fichier header (SecondViewController.h).  Au final celui-ci doit ressembler à ceci :


@interface SecondViewController : UIViewController {
    IBOutlet UITextField *txtTo;
    IBOutlet UITextField *txtSubject;
    IBOutlet UITextView  *txtBody;
}

- (IBAction)send:(id)sender;
- (void) sendEmailTo:(NSString *)to withSubject:(NSString *) subject withBody:(NSString *)body;

Ici nous définissons de plus deux méthodes. Une liée à la gestion d'événement (IBAction) pour le bouton, et l'autre réalisant l'envoi d'e-mail. La première sera activée lors du clic sur le bouton et fera appel à la seconde.
Voyons donc cette méthode :


-(IBAction) send:(id) sender {
    //Fait appel à la méthode sendEmailTo: avec les paramètres associés
    [self sendEmailTo:txtTo.text withSubject:txtSubject.text withBody:txtBody.text];
}

- (void) sendEmailTo:(NSString *)to withSubject:(NSString *) subject withBody:(NSString *)body {
    
    //Construit une chaine de caratères contenant nos données
    NSString *mailString = [NSString stringWithFormat:@"mailto:?to=%@&subject=%@&body=%@",
                            [to stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding],
                            [subject stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding],
                            [body  stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
    
    //Ouvre l'application Mail "mailto:" avec les données pré-saisies
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:mailString]];
}

Elle prend donc 3 arguments : l’adresse, l’objet et le message (c’est mieux pour un mail !). Puis elle construit une chaîne de caractère à l’aide d’une fonction permettant la mise en forme de celle-ci (par exemple les espaces seront remplacés par des %20 ...). Cette chaîne de caractère ou string aura donc le format d’une URL. C’est donc exactement comme ci nous avions réalisé un lien «mail» sur une page web.

Bien sûr il existe d’autres méthodes pour envoyer un mail. Une des "astuces" permettant d'envoyer un mail sans passer par l'application native Mail est de passer par des méthodes POST (avec nos paramètres) sur un serveur qui se chargera de l'envoi. Mais ceci est un autre sujet...

Il ne nous reste plus qu’à réaliser la méthode appelée lors du clic :


-(IBAction) send:(id) sender {
    //Fait appel à la méthode sendEmailTo: avec les paramètres associés
    [self sendEmailTo:txtTo.text withSubject:txtSubject.text withBody:txtBody.text];
}

Il ne s’agit ici que d’un appel vers la méthode précédente.

4) Delegate

À ce niveau notre code est fonctionnel. Néanmoins, un détail d’importance n’a pas été pris en compte : la rétractation du clavier après la saisie. En effet il est très important au niveau de l’expérience utilisateur que notre clavier se rétracte :


- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    if(textField == txtTo || textField == txtSubject) {
        //Permet la rétractation du clavier virtuel
        [textField resignFirstResponder];
    }
    return YES;
}

Pour que cette méthode soit appelée lors de l’appui sur la touche de retour du clavier, il nous faut déclarer notre ViewController comme «delegate» de nos «TextFields». Cela signifie que notre Controller va écouter tous les événements liés à ces «TextFields». Nous verrons au fur et à mesure de nos tutoriels que cette démarche est une des clés pour bien comprendre la programmation en Objective-C.

Pour déclarer notre ViewController comme "delegate" deux étapes sont nécessaires :

• La déclaration dans le .h (SecondViewController.h) :

@interface SecondViewController : UIViewController <UITextFieldDelegate>

• Relier les éléments à leur delegate :

Ici nous le ferons sous InterfaceBuilder. Il est également possible de le faire dans le code via la syntaxe suivante :

monObjet.delegate = monObjetViewController; //En général self

Pour rétracter le clavier nous allons juste ajouter une ToolBar comportant un bouton à notre seconde vue :

http://www.ipup.fr/forum/userimages/Capture-d-ecran-2010-03-27-a-18.22.03.png



Comme nous l'avons déjà vu il nous suffit d'appeler la méthode resignFirstResponder lors du clic sur le bouton Done


- (IBAction)dismissKeyboard:(id)sender {
    [txtBody resignFirstResponder];
}

Voilà, nous avons presque terminé, retournons à Interface Builder pour relier nos éléments comme nous en avons maintenant l’habitude.



Besoin d’une piqûre de rappel ?

En premier lieu, il faut définir le File’s Owner de notre fichier «SecondView.xib» comme appartenant à la classe SecondViewController. Ainsi après avoir sélectionné le File’s Owner choisissons l’onglet identity dans l’inspecteur, puis SecondViewController dans le champ classe.

Pour continuer, sélectionnons l’onglet Connections et relions nos Text Field et notre Text View à nos élements d’interface. Pour les Text Field il faut également rattacher le champ delegate au File’s Owner (dans l’onglet Connections du Text Field).

Enfin il faut relier la méthode "Envoyer" à l’élément dont elle gère les événements c’est à dire au bouton (choisir l’option Touch Up Inside).




Un petit  <+R> dans Xcode après avoir sauvegardé vous permettra d'apprécier le travail fourni ! tongue

Important : ne vous inquiétez pas si l’envoi de mail ne fonctionne pas sur le simulateur ! En effet celui ci n’a pas accès au bonnes ressources. Notre application fonctionnera donc parfaitement sur un iPhone !

Merci d’avoir suivi ce tutoriel ! À bientôt !



Petit exercice

Pour aller un plus loin dans notre compréhension des différents éléments du SDK, reprenons notre tutoriels et améliorons un peu l'ergonomie et l'interface utilisateur. En effet pour que l'aspect fonctionnel d'une application soit apprécié à sa juste valeur, l'accent doit être mis sur l'ergonomie et l'expérience utilisateur. C'est d'ailleurs là l'une des principales valeur ajoutée de l'iPhone. Le succès d'une application passera donc nécessairement par une reflexion et un ajustement de cette fameuse expérience utilisateur.

Pour cela nous rajouterons une Activity Indicator View (UIActivityIndicatorView) lors du temps de chargement de la page Web.
Nous ajouterons également une Alert View (UIAlertView) pour confirmer l'envoi du mail.
Enfin nous allons rendre la ToolBar, servant à la rétractation du clavier, dynamique.

Comme cette partie est un peu plus complexe faisons la ensemble.

Tout d'abord il faut que notre second ViewController puisse "écouter" les événements de la TextView et notamment le début de la saisie. Pour cela il faut qu'il soit un delegate de UITextView :


@interface SecondViewController : UIViewController <UITextFieldDelegate, UITextViewDelegate>

Pour mieux comprendre il y a toujours la doc !

Documentation Xcode

http://www.ipup.fr/forum/userimages/Capture-d-ecran-2010-03-27-a-18.39.33.png



Nous arrivons à :


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
    [toolBar setHidden:YES];
}


- (BOOL)textViewShouldBeginEditing:(UITextView *)textView {
    [toolBar setHidden:NO]; // Dans le .h : IBOutlet UIToolBar *toolBar;
    return YES;
}

N'oublions pas de relier le TextView à son delegate.

Un petit aperçu :

http://www.ipup.fr/forum/userimages/Capture-d-ecran-2010-03-27-a-19.19.08.png


http://www.ipup.fr/forum/userimages/Capture-d-ecran-2010-03-27-a-19.22.02.png



Bon courage wink !

Aurel

code source

Copyright © 2009 - ipup.fr • création de Jérémy Lagrue • design de Loann Fraillon • contact