Bindings, preferences, clé, notification...

muqaddarmuqaddar Administrateur
12:53 modifié dans API AppKit #1
Salut,

Soit un gestionnaire de preferences.
Soit un outlet NSTextField qui ne peut qu'être rempli par un setStringValue.

Je remplis donc le field avec du texte (une chemin de fichier en l'occurence qui provient d'un NSOpenPanel).

Le field est bindé sur sa value, mais il ne m'enregistre pas la modification de valeur...

J'ai alors pensé faire un KVO :

<br />// observe sound selection changing<br />[[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@&quot;soundNamePrefPanel&quot; options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:nil];<br />


et

<br />- (void)observeValueForKeyPath:(NSString *)keyPath<br />					&nbsp; ofObject:(id)object<br />						change:(NSDictionary *)change<br />					&nbsp;  context:(void *)context {<br />	if ([keyPath isEqual:@&quot;soundNamePrefPanel&quot;]) {<br />		NSlog (@&quot;toto&quot;);<br />	}<br />}


mais ça n'a pas l'air bénéfique... par ailleurs, que mettre dans le dernier if ?

Réponses

  • 12:53 modifié #2
    Il me semble que tu dois mettre l'observer sur le NSUserDefaultsController. Vague souvenir, je ne suis pas plus sur que ça.
  • AliGatorAliGator Membre, Modérateur
    janvier 2006 modifié #3
    J'ai eu un cas similaire (sauf que ne j'avais pas à  mettre un Obeserver sur ma valeur, moi), et en cherchant dans la doc j'ai vu que les setStringValue sur les NSTextField (ou autres) n'affectaient pas la valeur dans les UserDefaults... même si le TextField était bindé à  ces derniers.

    En gros c'est pour mon appli "GPS PUI Grabber" (que j'ai mis dans Beta-tests) : j'ai un NSTextField pour afficher le chemin du dossier, et un bouton "Choisir" qui m'affiche un NSOpenPanel et récupère le dossier sélectionné. J'ai bindé mon textfield aux NSUserDefaults en lui donnant un nom de clé. Mon NSTextField à  moi était éditable, par contre.

    Et bien au début, la valeur n'était mémorisée dans les NSUserDefaults que si je la rentrait à  la main (modification du contenu de mon TextField). Par contre si je cliquais sur mon bouton qui affiche mon NSOpenPanel, et qui faisait un [tt][champPath setStringValue];[/tt], le champ changeait bien de valeur mais cette valeur n'était pas sauvegardée dans les NSUSerDefaults ! ???

    Ce n'est qu'après que j'ai compris en cherchant d'où ça venait et lisant la doc qu'il fallait modifier la valeur dans le controlleur des valeurs et non directement dans le TextField. J'ai donc remplacé par un [tt][[NSUserDefaults standardUserDefaults] setValue:lePath forKey:@pathToFolder];[/tt] et là  ça a tout de suite marché :o

    Et bien sûr, grâce aux bindings et au KVO tout se fait tout seul, c'est à  dire qu'en changeant dans le NSUserDefaults, mon champ se met à  jour dans ma fenêtre :o

    Donc toi si ça se trouve tu fais un setStringValue sur ton champ et donc le NSUserDefaults n'est pas modifié. Et par la même occasion, tu as beau mettre un observer de ta valeur dans le NSUserDefaults, vu qu'elle n'a pas été modifiée (seulement le champ dans l'interface mais pas dans le UserDefaults), ben tu peux toujours attendre une notification de modification de ta valeur... ::) :P
  • muqaddarmuqaddar Administrateur
    janvier 2006 modifié #4
    Salut AliGator,

    Et bein, en fait, tu as toute deviné !
    J'ai eu exactement le même problème que toi. Avec un retour de NSPanel à  gérer.

    Donc, tu avais presque bon.
    Dans mon cas, j'ai du faire un "forKeyPath".

    [[NSUserDefaults standardUserDefaults] setValue:[sheet filename] forKeyPath:@soundNamePrefPanel];

    et là , ça baigne, adieu outlet !

    ;)
  • AliGatorAliGator Membre, Modérateur
    janvier 2006 modifié #5
    Heu oui c'était forKeyPath bien sûr et non pas forKey, puisque les bindings ne fonctionnent par les KeyPath, j'avais mis ça de mémoire... :brule:

    Surtout que j'utilise peu les profondeurs au dela de 1 dans les keyPath de mes bindings pour l'instant, d'où la confusion que j'ai faite
    (car dans ce cas le KeyPath, n'ayant pas de "." ou quoi, ressemble fort à  une Key normale, à  la limite c'en est même une ;))
  • muqaddarmuqaddar Administrateur
    12:53 modifié #6
    Merci à  toi en tout cas !
  • AliGatorAliGator Membre, Modérateur
    janvier 2006 modifié #7
    Allez, petite précision pour rajouter une autre pierre à  l'édifice :

    Plutôt que de modifier la valeur dans le NSUserDefaults directement, il est aussi possible d'accéder au NSUserDefaultsController.

    Par contre si quelqu'un sait s'il est préférable d'utiliser l'un plutôt que l'autre...
    Genre faut-il préférer :
    [[NSUserDefaults standardUserDefaults] setValue:@&quot;myvalue&quot; forKeyPath:@&quot;mykey&quot;];
    
    ou
    [[[NSUserDefaultsController sharedUserDefaultsController] values] setValue:@&quot;myvalue&quot; forKey:@&quot;mykey&quot;];
    
    ???

    Dans la doc ici on peut lire :
    Although NSUserDefaults should remain your primary programmatic interface to the user defaults, some circumstances require that you get and set the default values contained in an NSUserDefaultsController instance directly. For example, when implementing portions of your preferences window that don't directly interact with an existing binding, such as setting a font or choosing a directory path.
    Mais j'ai du mal à  capter : en gros lorsque l'on a par exemple une préférences qui n'interagit pas directement en tant que binding, alors cela peut être un cas où on doit accéder au NSUserDefaultsController plutôt qu'au NSUserDefaults directement ? J'aurais plutôt dit l'inverse, moi...
Connectez-vous ou Inscrivez-vous pour répondre.