• Billet écrit dans : Mobile, iPhone 06.04.2009 7 Réactions !!

    Bonjour,

    Voici juste un petit « How to » pour comprendre et jour avec les delegate sur cocoa.

    Admettons vous avez une classe « ListingController » qui hérite d’une UIViewController qui gère une liste d’élément et que vous avez une classe « DetailController » qui hérite aussi d’une UIViewController mais qui donne le detail de l’élément cliqué.

    Vous voulez que lorsqu’on click sur un bouton posé sur la vue Détail revenir à la liste principal, puis la recharger. Revenir à la vue principal est assez simple il suffit de crée une méthode « IBAction » dans le controller Detail, liée le bouton à cette méthode via Interface builder puis écrire  :

    1
    2
    3
    
    -(IBAction)goHome {
    [self.view removeFromSuperview];
    }

    Et le tour est joué mais bon, la liste n’est pas rechargé pour autant et il n’y a pas eu la levé d’un évènement pour la classe « Liste ». C’est là que les delegate peuvent nous être utile.

    Le principe est de définir des méthodes sur la classe de Detail puis les appeller/utiliser lors du click mais c’est la classe Liste qui les implémentera effectivement.

    Voici la marche à suivre :

    1. Dans la classe Detail : Définir une ou plusieurs méthodes dite « delegate » qui devront être implémenter. On appelle ce genre de déclaration un « protocole ».
    2. Dans la classe Detail : Définir une propriété de classe de type « id » qui utilise le protocole. Cette propriété représente un lien vers la classe « parente » qui implémentera effectivement notre protocole.
    3. Dans la classe Detail : Appeller lors du click les méthodes « delegate » sur notre protocole.
    4. Dans la classe Liste : Implémenter les méthodes delegate dans notre classe « parente ».

    Etape 1 :

    Dans le fichier « DetailController.h », juste après les #import et avant @interface DetailController : UIViewController { } :

    1
    2
    3
    4
    
    @protocol DetailControllerDelegate
    @required
    -(void)RetourListe;
    @end

    Etape 2 :

    Toujours dans le fichier « DetailController.h », après « @interface DetailController : UIViewController { » nous définissons une propriété que nous appellerons « delegate » :

    1
    
    id delegate;

    puis après l’accolade définissant l’interface :

    1
    2
    3
    
    @property (nonatomic,assign) id < DetailControllerDelegate > delegate;
     
    @end

    Notre propriété « delegate » est de type « id » mais « implémente » le protocole précédement utilisé.

    Etape 3 :

    Nous avons définit une propriété dans le fichier « .h », il faut maintenant s’en servir dans notre fichier « DetailController.m » :

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    #import "DetailController.h"
    @implementation DetailController
    @synthesize delegate; //synthetisé une propriété signifie que le sdk créera les getters/setters pour nous
    -(IBAction)goHome
    {
    	NSLog(@"Go home Liste");
    	[self.delegate RetourListe]; // dispatch l'évènement à la classe parente.
    	[self.view removeFromSuperview]; // supprime la vue courante
    }

    C’est fini pour notre classe Detail  ! Vous remarquerez qu’à aucun moment il n’y a de lien vers la classe « Liste ». Le couplage est donc très faible entre ces classes. Ce principe de couplage faible est assez puissant si on y réfléchi à deux fois vu que nos classes sont, de fait, totalement indépendantes vis à vis de leur « parent » (ou du contexte d’execution pour être plus bien parlant). Bon bref ça c’était le coup de pub raté pour la puissance du modèle objet.

    Etape 4

    Implémentons les méthodes ! Dans le fichier « ListingController.h » nous déclarons notre interface comme ceci :

    1
    2
    3
    
    @interface ListingController : UIViewController < DetailControllerDelegate > {
    // some code
    }

    Et dans notre fichier « ListingController.m » il suffit d’implémenter la méthode « RetourListe ». Surtout, ne pas la déclarer dans l’interface (le fichier .h) sinon le programme se mélangera les pinceaux ! (Oui, vous utilisez deux méthodes avec le même nom ayant des portés différentes ..)

    1
    2
    3
    4
    5
    
    -(void)RetourListe
    {
        NSLog("coucou");
        // some code
    }

    Edit : Oups, erreur. On crée la méthode mais à un aucun moment on dit que notre classe Listing va implémenter les méthodes de detail hormis dans la déclaration (fichier.h). Il faut donc qu’à notre objet « DetailController », juste après qu’il soit instanciée, au moment du click par exemple faire un :

    1
    2
    
    DetailController*myView = [[DetailControlleralloc] initWithNibName:@"DetailView" bundle:[NSBundle mainBundle]];
    myView.delegate = self;

    On définit que c’est la classe Listing (self) va implémenter les méthodes delegate de détail.

    Et voilà, normallement ça doit marcher.

    Ce « How to » a été écrit à partir d’un projet personnel, je ne pourrais donc pas donnée des sources qui utilisent ce concept. A l’heure où j’écrit ce billet je n’ai pas de Mac à ma disposition.

    Billet écrit dans : Mobile, iPhone 06.04.2009 7 Réactions !!
CV Guillaume chave