[Résolu] Quand les relations deviennent tendues, faut-il notifier?

berfisberfis Membre
juin 2013 modifié dans API AppKit #1

Bonjour!


 


Imaginons qu'une application fasse appel à  de nombreuses classes, qui ont certes un rapport entre elles, mais dont le voisinage dans la structure générale se fasse lointain.


 


Disons que dans une fenêtre, j'ai une tableView basée sur des vues, qui contiennent des subviews, comprenant des boutons ou des indicateurs. On a bien sûr moyen de savoir si un bouton a été pressé grâce au mécanisme target/action, mais c'est moins évident quand, par exemple, on n'a aucune idée à  la compilation de ce que sera ce target... C'est un exemple parmi d'autres.


 


Je voudrais en fait qu'un objet qui subit une modification quelque part à  l'exécution clame à  qui voudra l'entendre "Hé, j'ai été modifié / je suis arrivé au bout de mon timer / etc...". Si quelqu'un l'entend, il prendra des mesures, sinon... il ne se passera rien.


 


Il me semble que c'est le travail des Notifications. Si j'ai bien compris, tout objet peut émettre une notification, et tout objet peut en recevoir (à  condition d'être inscrit au centre de notifications et de posséder une méthode capable de répondre). Ne serait-ce pas là  un bon moyen de réduire les dépendances entre classes, le nombre de leurs propriétés et le code fouilli genre:


if ([self.superviseur.isActive]) [[self.superviseur.superviseur.indicateur]setNiveau: 0] ou pire encore?


 


Reste à  voir (si c'est une bonne idée) comment ça marche...


 


Avez-vous de l'expérience dans ce domaine?


Réponses

  • samirsamir Membre

    Bonjour,


     


    Je trouve que ta question est un peu vague, à  mon avis :), le mieux c'est de poster le code/pattern/procédé qui te semble pas correct/marche pas et de discuter dans le forum, je te dit ça par ce que moi meme je posais des question un peu vague et j'ai remarqué que les gens ne comprennent pas vraiment ce que je voulais dire, et c'est de ma faute bien sur :).


     


    Sinon, si j'ai bien compris ta question, si l'objet qui subit la modification doit informer un seul objet, dans ce cas tu peux utiliser le pattern Delegation, sinon si plusieurs objets, c'est les notifications.

  • Comme son nom l'indique, le pattern Délégation est plutôt pour déléguer une ou plusieurs tâches à  un autre objet. Le couplage est relativement fort entre un délégué et son délégateur.


     


    Le pattern Notification est utilisé pour communiquer des événements avec un couplage faible voire nul. On conçoit une classe "notificatrice" lorsque les événements notifiés peuvent être attendus par une large gamme d'autres classes.


  • jpimbert,


    J'aimerais bien avoir du code qui ne marche pas pour vous le soumettre... mais entretemps le mien marche, avec une telle facilité que c'est à  se demander pourquoi j'ai ouvert ce sujet. En fait c'est plutôt simple. L'objet qui poste la notification fait ceci:



    [[NSNotificationCenter defaultCenter]postNotificationName:@DisCoucouNotification object:self];

    et l'objet qui est censé réagir fait ça:



    [[NSNotificationCenter defaultCenter] addObserver:self
    selector:@selector(recoitCoucou:)
    name:@DisCoucouNotification object:nil];

    L'objet qui émet la notification est passé au sélecteur recoitCoucou, pour le retrouver on fait ça:



    - (void)recoitCoucou: (NSNotification*)aNotification
    {
    MonObjet *monObjet= [aNotification object];
    ...
    }

    C'est simple, c'est threadsafe, et si un autre objet veut réagir, il s'abonne et implémente son propre recoitCoucou...


     


    En effet, c'est ce que je cherchais, parce que je ne veux pas de couplage fort entre classes.


  • La seule difficulté avec le pattern Notification de Cocoa et CocoaTouch c'est qu'il faut penser à  désabonner les objets avant leur destruction, dans leur méthode dealloc par exemple. Le centre de notification de Cocoa n'est pas encore "memory-safe".


  • dealloc n'est pas autorisé avec ARC. J'espère que les gars d'Apple y ont pensé...


  • AliGatorAliGator Membre, Modérateur
    dealloc est tout a fait autorisé en ARC, sauf que maintenant il ne sert... qu'à  ça quasiment.


    Avant ARC il fallait implémenter dealloc pour faire tous les release sur les ivars. Maintenant que release est interdit avec ARC car c'est ARC qui s'en charge, tu n'as plus besoin d'implementer dealloc pour ça. Mais si tu en as besoin pour autre chose, pas de souci il existe encore. Soit pour liberer de la memoire qui ne serait pas geree par ARC (genre un bon vieux "malloc()" du monde C à  libérer avec un "free()") soit justement pour te désabonner du NotificationCenter


    PS : sinon ARC gère lui-même l'appel à  [super dealloc] qu'on avait à  rajouter à  la fin quand on écrivait notre dealloc. Si je ne dis pas de bêtises, maintenant c'est ARC qui s'en charge aussi donc tu n'as plus à  le faire (et même n'a plus le droit de le faire) même si tu implémentes ton dealloc pour t'enlever du NotifCenter.
  • Donc si un "récepteur" a la même durée de vie que l'application, je n'ai rien à  faire (étant donné qu'un émetteur n'est pas enregistré)?


  • Effectivement si tu ne fais rien ça marche.


     


    Mais je t'invite tout de même à  ajouter un dealloc bien propre. ça ne coûte que trois lignes de code et ça te facilitera la vie dans quelques mois, quand tu voudras modifier ton code et que tu auras oublié que ta classe abonnée doit impérativement avoir la durée de vie de l"application.


     


    Règle n°42 de la maintenabilité : remplacer une connaissance implicite par du code bien concret


     


    PS : ne cherche pas les 41 premières règles. J'ai mis 42 simplement car c'est un nombre à  la mode.


  • AliGatorAliGator Membre, Modérateur
    Y'a des nombres avant 42 ?!
  • Décidément, 42 est la réponse à  la Grande Question sur la Vie, l'Univers et le reste...


  • Comme ce n'est pas tout à  fait ma génération j'avais loupé ça. Mais ça y est j'ai entrepris un recyclage de fond ; j'ai commencé à  lire la trilogie en cinq volumes.


  • Finalement il se trouve que dealloc est appelé trop tard. Je recycle assez rapidement mes objets et l'application part aux fraises.


     


    Comme on n'appelle pas dealloc soi-même, j'ai donc rajouté à  la classe une méthode "dispose" que j'appelle au moment voulu et qui retire l'objet du centre de notification. Après, le système peut désallouer mes objets quand il veut, ça m'est égal.


     


    @jpimbert: j'ai bien sûr commenté le code pour le moi qui relira ça dans six mois en se demandant ce que c'était que cette méthode idiote...


Connectez-vous ou Inscrivez-vous pour répondre.