Récupérer le contenu d'un NSArrayController

cargocargo Membre
01:39 modifié dans API AppKit #1
<br />- (NSNumber*) monNombre<br />{<br />return [NSNumber numberWithDouble:[[outlet_monArrayController valueForKeyPath:@&quot;selection.maValeur&quot;]doubleValue]];<br />}<br />


Ce code est dans une catégorie de MyDocument.
J'ai un textField bindé comme suit pour récupérer monNombre :
Bind to: File's Owner
Ck :----
Mkp : monNombre

Le résultat dans le textField est comme si la sélection était vide en fait (mot selection grisé), il ne m'affiche pas le nombre.
Je ne comprends pas.

L'outlet est ok.
Si je bind le textField directement au controller dans IB pas de problème il m'affiche la valeur souhaitée.
Si je renvoie le nombre 1 par exemple dans la catégorie de MyDocument, pas de problème il l'affiche.

Peut-être parce que je ne passe pas par le managedObjectContext en fait, je bind en direct sur le file's owner ?
Je ne sais pas, je pète un câble. L'exemple ici est simplifié, en fait j'en ai besoin pour faire qqchose de plus complexe.
:why?:

Réponses

  • fouffouf Membre
    01:39 modifié #2
    C'est parce que monNombre n'est pas appelée quand la selection change. En effet, si tu bindes directement l'array controller et le textField, le textField sera mis à  jour quand la selection changera, mais ce n'est pas le cas quand tu bindes à  mon nombre.
    La solution est la suivante : il faut que tu observes (avec KVO) la selection de l'arrayController et que tu utilises willChangeValueForKey: et surtout didChangeValueForKey: et normalement tout devrait rentrer dans l'ordre ...
  • cargocargo Membre
    01:39 modifié #3
    C'est dans cette direction que j'allais. Je me suis aperçu que le monNombre était bien capable de faire le calcul initialement mais pas de changement par la suite.
    Donc je dois ajouter un observer dans awakeFromNib (ou dans inithWithType?) c'est à  dire que j'ajoute MyDocument comme un observer de selection.maValeur (ou de selection tout court?). Je suppose que je dois le remover à  la fin de l'exécution de l'appli.
    Le problème au niveau des accesseurs (car j'ai déjà  essayé) c'est que [self willChangeValueForKey...] ça marche pas apparemment dans MyDocument, j'ai une alerte comme quoi il ne répondrait pas à  willChangeValueForKey. Je me demandais si c'était normal d'avoir des accesseurs dans MyDocument, normalement ça concerne le modèle ça, mais dans le modèle on ne peut pas récupérer le contenu dans arrayController...
    Ou alors binder dans le code ? Qu'est ce que je pourrais binder à  ce controller dans le code en fait ? J'aimerais bien savoir ce qui est sous-jacent au binding, ça m'aiderait...

  • cargocargo Membre
    01:39 modifié #4
    mmm
    Ca ça me rassure pas :
    http://www.objective-cocoa.org/forum/index.php/topic,2019.0.html
    Je crois que je vais me tourner vers une autre solution...
  • fouffouf Membre
    01:39 modifié #5
    Il faut que tu ajoutes le KVO dans awakeFromNib (il faut que les outlets soient mis en place) et qu'il observe selection (tu as besoin de mettre a jour le text field lorsque la selection change) .
    Le fait d'avoir des accesseurs dans un controller n'est pas un problème. En effet, le MVC n'est qu'une convention (donc aucune obligation de coder en style MVC avec Cocoa) et qui en plus n'interdit pas de mettre des accesseurs à  un controlleur ou a une vue. Imaginons par exemple un vue avec un mécanisme de zoom : il va bien falloir stocker la valeur de ce zoom quelquepart et ca surement pas dans des modèles donc soit dans la vue, soit dans le controlleur.

    Finalement, dans ton MyDocument.m, tu dois faire un truc du genre :

    <br />- (void)awakeFromNib<br />{<br />&nbsp; &nbsp; [_arrayController addObserver:self <br />			&nbsp; &nbsp; &nbsp;  forKeyPath:@&quot;selection&quot; <br />				&nbsp; &nbsp; options:NSKeyValueObservingOptionNew <br />				&nbsp; &nbsp; context:nil]; 						<br /><br />}<br /><br />- (void)observeValueForKeyPath:(NSString *)keyPath <br />					&nbsp; ofObject:(id)object <br />						change:(NSDictionary *)change <br />					&nbsp;  context:(void *)context<br />{<br />	[self willChangeValueForKey:@&quot;monNombre&quot;];<br />	[self didChangeValueForKey:@&quot;monNombre&quot;];<br />}<br /><br />
    


    Si tu utilises déjà  le KVO dans ton MyDocument, tu as intérêt à  tester keyPath ou object pour vérifier que c'est bien la bonne clé (selection) ou le bon object (_arrayController) ...
  • cargocargo Membre
    01:39 modifié #6
    Et c'est "là " que je met mon calcul de valeur non ? J'avais pas pigé comment implémenter cette fonction...
    <br />[self willChangeValueForKey:@&quot;monNombre&quot;];<br />/// &quot;là &quot; je fais le calcul ...<br />[self didChangeValueForKey:@&quot;monNombre&quot;];<br />
    


    Du coup je comprends plus comment binder mon textField cà d récupérer mon résultat, puisque je fais mon calcul dans une fonction void. Ou alors je fais le calcul ailleurs et "là " je récupère la valeur et je l'attribue à  la clef...

    En tous cas merci, c'est + clair déjà .  ::)
  • fouffouf Membre
    01:39 modifié #7
    Oui tu peux faire le calcul "là " ou bien dans l'accesseur lui-même sachant que faire le calcul dans l'accesseur réduit un peu les perfs mais évite les problèmes de non mise-à -jour éventuels (genre une mauvais syncro ou que sais-je encore ...). Le truc c'est qu'il faut que tu bindes ton textField a la clé qui retourne le résultat de ton calcul. Si tu fais le calcul dans la fonction void, il faut que tu utilises une variable de classe pour te "souvenir" du résultat.
Connectez-vous ou Inscrivez-vous pour répondre.