Pointeurs, string et binding : question de conception
Bonjour,
voilà mon problème :
J'ai deux classes : une classe A et une classe B.
Comment faire en sorte que les mises à jour du texte faites dans la fenêtre (via classe B ) soit prises en compte par classe A ?
J'ai pensé à deux solutions qui ne fonctionnent pas :
Avez-vous des idées ?
Je n'ai pas encore testé mais j'ai pensé à un NSMutableString.
Je voulais avoir vos idées là -dessus car il me semble que c'est assez classique.
Merci !
voilà mon problème :
J'ai deux classes : une classe A et une classe B.
- La classe A a un attribut NSString, disons myText.
- La classe B est chargée de présenter ce texte dans une fenêtre pour l'éditer.
La classe B est appelée par la classe A.
Comment faire en sorte que les mises à jour du texte faites dans la fenêtre (via classe B ) soit prises en compte par classe A ?
J'ai pensé à deux solutions qui ne fonctionnent pas :
- Ajouter un attribut myTextForB dans classe B.
Créer une méthode d'initialisation initClassBwithString.
Quand la classe A crée classe B, lui passer myText en argument.
Dans la classe B, faire un binding (via IB) entre myTextForB et le NSTextView
ça ne marche pas, car quand classe B modifie la valeur des chaà®nes de caractère, elle change l'adresse. En gros, myText dans classe A pointe toujours sur la même string. - Du coup, je me suis dit :
Faire le binding dans le code, directement.
Passer l'objet A comme argument lors de l'initialisation à B.
Dans une méthode de type awakeFromNib créer un binding, du genre :
<br /> [myTextView bind:@"value" toObject:objetA withKeyPath:@"myText" options:nil] ; <br />
Je ne sais pas pourquoi, mais ça ne marche pas.
Avez-vous des idées ?
Je n'ai pas encore testé mais j'ai pensé à un NSMutableString.
Je voulais avoir vos idées là -dessus car il me semble que c'est assez classique.
Merci !
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
=> A est ta classe modèle
=> B est ta classe contrôleur (car tu conceptualise en MVC bien sur).
Donc B doit instancier A, ou avoir un pointeur vers A, et va "binder" ce pointeur avec le textfield qui le présente.
nan ?
Dans mon cas, A est une NSDocument et B une NSWindowController
Pour le 2) Si A est une propriété de B alors tu peux lier bTextView.value à self.A.myText.
Pour le 1) Ecrire le setter de myTextForB et dedans faire la modification de myTextInA.
Pour les 2 : mettre des points d'arrêt et regarder les valeurs des objets : un objet nil ne lance pas d'erreur quand on lui envoie un message, le message est simplement ignoré ..
NB : On peut mettre un point d'arrêt sur @synthesize pour regarder la valeur d'une propriété quand elle est accédée ..
Buy Diablo 3 Gold
Cheap Diablo 3 Gold
Buy Guild Wars 2 Gold
WTF ?
Oui, j'envoyais des messages à nil.
En fait, j'essaye d'accéder au document en cours à l'aide de la commande
Mais, il semble que cette commande ne marche pas quand je l'appelle depuis un NSWindowController. Comme si le fait que ce soit une nouvelle fenêtre lui fasse perdre le chemin du document en question.
Du coup, je me demande si ce serait pertinent de lui passer le document en cours en argument.
Sinon,
<< [font=helvetica, arial, sans-serif]Pour le 1) Ecrire le setter de myTextForB et dedans faire la modification de myTextInA. >>[/font]
c'est très joli !
Merci !
PS :
Pour le binding dans le code, ce qui suit te semble-t-il OK ?
Il faut décocher l'option "Rich Text" dans IB.
Les bindings c'est le bazar ...
merci !
PS : j'avais bien décocher RTF, mais c'est peut-être ce "continuous update" qui me manquait...
ça marche, en passant mon NSDocument en argument à mon NSWindowController
Rien n'y fait, ça ne marche toujours pas avec les bindings "dans le code".
Merci quand même !!
(L'autre solution marche)
Tu veux faire un lien entre un textView dans une fenêtre secondaire avec une variable d'instance de ton document.
La méthode qui implémente ce lien doit connaà®tre à la fois le textView et la variable d'instance.
Est-ce que le document doit connaà®tre un objet d'interface qui se trouve dans une fenêtre secondaire, à priori non, c'est au windowController de cette fenêtre.
Si on considère que NSDocument est le controller maà®tre, alors c'est à lui de donner les ordres: toi windowController, établis-moi un lien entre ton textView et ma variable.
Donc concrètement, j'ajouterais au WindowController une méthode du genre:
Sinon, je ne suis pas persuadé que dans ce cas précis les bindings soient vraiment indispensable, à moins que tu veilles une mise à jour en continu de la variable de ton document.
La réponse est dans la documentation
Quand l'objet en cours d'édition arrête de l'être, autrement dit quand l'utilisateur quitte le champ (ou la vue) via la touche tabulation | enter | retour-chariot | click dans une autre vue...
Il semble (dans le cas d'une fenêtre auxiliaire) que quand je ferme la fenêtre, le update n'est pas fait.
J'ai une hypothèse là -dessus :
dans mon code, j'initialise ma fenêtre auxiliaire et dans la foulée je crée mon binding.
Mais alors je vais trop vite car la NSTextView n'a pas eu le temps de se réveiller du NIB.
J'ai déjà été confronté à ce genre de problème.
Par exemple, je dois faire un [myTextField setStringValue:@Coucou] juste après une init.
La méthode que j'ai trouvée, mais que je ne trouve pas super élégante (à mon avis il doit y avoir des défauts de conception dans mes classes) c'est un truc du genre :
Quand je dis qu'il y a un problème de conception, c'est peut-être parce que tous mes NIB devrait être appelés au début ?
Mes fenêtres auxiliaires (genre préférences) devraient être réveillées dès le début ?
D'un autre côté, les réveiller alors que personne ne va les appeler, c'est peut-être utiliser de la mémoire pour rien.
Au final, il y avait deux problèmes :
Merci de votre aide
PS : ce qui serait bien, ce serait d'avoir dans Cocoa, des méthode du genre :
et de même pour les NSView
(Remarque :
J'ai @property ;(unsafe_unretained) IBOutlet NSTextView *preambuleTextView;
sans @synthesize
mais xCode ne me gueulait pas dessus quand j'utilisais la variable preambuleTextView, au lieu de _preambuleTextView...
ce qui m'a fait perdre 10minutes
Est-ce normal qu'il ne m'ait pas engueulé ?
)
Ajoute le windowController au document et regarde si ça change quelque chose.
- (void)addWindowController:(NSWindowController *)aController (NSDocument)
x
Mystère : le document est maintenant reconnu direct sans ta méthode !
Je ne sais pas ce qui s'est passé !
En somme, un long détour pour rien
Mais merci quand même !
J'ai la réponse et cela pourra vous interpeler je pense
Voilà mon préambule :
mais je n'ai pas de
Et le bilan de tout ça : c'est que preambuleTextView est nil !!!
Mais pas _preambuleTextView !!
à‰trange !
Mais je suis sûr que ceux qui comprennent bien tout ceci ont une explication.
Merci !
Si tu n'as pas de @synthesize, par défaut la propriété preambuleTextView est attachée à la variable d'instance _preambuleTextView.
Le compilateur ne t'empêche pas de définir une autre variable d'instance preambuleTextView.
Mais c'est périlleux car la confusion est facile. La preuve ...
Bien vu !
Tout est normal, l'informatique ce n'est pas de la magie ...
Lorsque que tu fais:
[[NSDocumentController sharedDocumentController] currentDocument]
à partir du windowController secondaire, cette méthode recherche qu'elle est la fenêtre active (main window) et recherche à quel document appartient cette fenêtre. Comme cette fenêtre secondaire n'appartient à aucun document, cette méthode retourne nil.
Mais si tu ajoutes ce windowController au document, le problème disparaà®t, logiquement !
Maintenant, cette fenêtre secondaire est à priori une mauvaise idée (bad design), il serait plus pertinent de l'afficher comme une sheet ou alors comme une palette (NSPanel).
Un NSPanel actif n'est pas main window, donc tu peux savoir à partir de ce panel qu'elle est le document actif, via la méthode sus-cité.
Oui, mais je ne l'ai pas ajoutée !
Whoua ! c'est magique alors