Jouons avec les notifications

muqaddarmuqaddar Administrateur
février 2007 modifié dans API AppKit #1
Dans ce cours article, je propose un petit exercice pour comprendre les bases du fonctionnement des notifications, bases qui pourront bien sûr être utiles au débutant en POO.

Comme exemple, nous travaillerons avec un système qui permet de surveiller tout changement effectué sur les objets d'un tableau, et qui avertit l'utilisateur pour une sauvegarde éventuelle si modification il y a eu.

Réponses

  • muqaddarmuqaddar Administrateur
    22:44 modifié #2
    Mise en place du système de notification

    Les notifications permettent aux applications écrites en Cocoa d'être au courant de nombreux informations émises par des évènements qui se passent à  l'intérieur d'une application, ou entres différentes applications.

    Dans cet exemple, les notifications vont nous permettre de surveiller tout changement effectué sur des objets de l'interface (capture ci-dessous). L'objectif étant d'être averti dès qu'une notification est signalée à  ce qu'on appelle le "NSNotificationCenter". Ce dernier inscrit des objets observateurs qui en surveilleront d'autres, justement, ceux-là  mêmes qui leurs envoient des notifications.


    [Fichier joint supprimé par l'administrateur]
  • muqaddarmuqaddar Administrateur
    22:44 modifié #3
    Trêve de paroles et de blabla. Passons à  notre exemple concret. ;-)

    Nous voici en présence d'une classe Controller, qui possède une méthode - (id)init dans laquelle nous allons inscrire nos objets observateurs :

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(recepteurDeChangements:) name:NSControlTextDidChangeNotification object:nil];<br />[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(recepteurDeChangements:) name:NSPopUpButtonWillPopUpNotification object:nil];<br />[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(recepteurDeChangements:) name:NSTableViewSelectionDidChangeNotification object:nil];<br />[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(recepteurDeChangements:) name:NSComboBoxSelectionDidChangeNotification object:nil];
    


    Ces 4 objets observateurs créés ont une particularité : les notifications sont des constantes. Ainsi, NSControlTextDidChangeNotification est appelé à  chaque fois qu'un champ de texte s'est modifié, NSTableViewSelectionDidChangeNotification est appelé à  chaque fois qu'on a sélectionné une nouvelle ligne dans une NSTableView, NSPopUpButtonWillPopUpNotification est appelé dès que la sélection change dans un popup, enfin NSComboBoxSelectionDidChangeNotification sera lui, appelé dès que la sélection a changé dans une comboBox. Cocoa fait bien les choses : les noms donnés aux notifications sont plus que parlants !

    Ces 4 notifications seront envoyées, grâce à  l'objet observateur, dans la méthode :
    - (void)recepteurDeChangements:(NSNotification *)notification
    

    où nous contrôlerons qui est l'objet notifié.

    Dans notre interface, nous devons également contrôler des objets qui n'ont pas de notifications appropriés : des NSButton (checkBoxes), et des NSMatrix. Nous allons allors leur associer une action qui postera une notification.
    Par exemple, nous leur associerons la méthode :
    - (IBAction)IBA_controleSelection:(id)sender
    dans laquelle on pourra écrire le code suivant :
    <br />- (IBAction)IBA_controleSelection:(id)sender<br />{<br />&nbsp; &nbsp; [[NSNotificationCenter defaultCenter] postNotificationName:@&quot;VNTCObjectChanged&quot; object:sender];<br />}
    


    Que faisons-nous ici ? Et bien, nous postons une notification personnalisée, qui a pour nom VNTCObjectChanged, et pour objet sender, c'est à  dire l'objet de l'interface où nous modifions la valeur. Dans notre cas, soit un NSButton, soit une NSMatrix.
    Bon, c'est bien beau tout ça, cependant, le NSNotificationCenter n'a pas d'observateur défini pour contrôler la nouvelle notification personnalisée. Il faut donc l'ajouter dans la méthode -(id)init :

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(recepteurDeChangements:) name:@&quot;VNTCObjectChanged&quot; object:nil];
    


    Le nouvel observateur (oui, elle est facile...) appellera également la méthode recepteurDeChangements: qu'il est temps de définir :

    - (void)recepteurDeChangements:(NSNotification *)notification<br />{<br />&nbsp; &nbsp; NSLog (@&quot;Notification : %@&quot;, [notification object] );<br />&nbsp; &nbsp; if (([[notification object] tag] &gt;= 1000) &amp;&amp; ([[notification object] tag] &lt;= 1200))<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; _isModified = YES;<br />&nbsp; &nbsp; }<br />}
    


    Dans mon exemple, j'ai auparavant créé une variable d'instance (booléenne) _isModified, initialisée à  NO dans le -(id)init.
    Ici, je demande simplement de contrôler le tag de l'objet envoyé par notification, afin d'être sûr qu'il s'agit uniquement des objets concernés par mon interface, et sur lesquels je veux que les notifications aient un rôle à  jouer. Si c'est le cas, je passe ma variable à  YES.

    Bien, mais quel est le but de tout ceci? Et bien, grâce à  la valeur de cette booléenne, je vais pouvoir agir sur l'enregistrement ou non de tous les champs concernés par les notifications. Il suffira d'une seule modification, sur un NSButton, un popup, une ligne de ma tableView...etc, pour que la variable d'instance passe à  YES et ainsi puisse déclencher cet éventuel enregistrement des modifications.
    Elle est pas belle la vie ? :-)

    Pour finir, on pourra "releaser" l'observateur, grâce à  la méthode removeObserver de cette façon, dans la méthode dealloc :
    -(void)dealloc<br />{<br />&nbsp; &nbsp; [[NSNotificationCenter defaultCenter] removeObserver:self];<br />&nbsp; &nbsp; [super dealloc];<br />}
    


    A vous les notifications !

    PS : un article beaucoup plus complet se trouve à  cette adresse.
Connectez-vous ou Inscrivez-vous pour répondre.