Update NSTextField <-> DataModel

lugdanumlugdanum Membre
13:50 modifié dans API AppKit #1
Bonjour tout le monde

Désolé pour le titre, mais je ne savais pas trop quoi mettre

J'utilise un DataModel et un NSTextField, quand je tape au clavier directement dans ce NSTextField, le texte est bien sauvegardé, j'ai aussi un bouton qui permet de choisir un dossier de destination, le chemin s'affiche ensuite dans ce NSTextField, mais là  par contre le texte n'est pas sauvegardé, comme si l'action n'était pas prise en compte.

Je pense que la personne ici à  le même problème que moi, mais j'ai pas compris non plus la réponse : http://forums.macrumors.com/showthread.php?t=490625

Mon code pour récupérer le chemin :
<br />NSOpenPanel *openPanel = [NSOpenPanel openPanel];<br />	[openPanel setCanChooseDirectories:YES];<br />	<br />	if([openPanel runModal] == NSFileHandlingPanelOKButton){<br />	[AfficheChemin setStringValue:[[openPanel URL] path]];<br />	}	<br />


Si quelqu'un peut m'éclairer, encore merci d'avance !

Réponses

  • mpergandmpergand Membre
    13:50 modifié #2
    Si je te suis bien .... la sauvegarde ne se produit qu'après un endEditing ( touche return ?)
    Donc pour sauvegarder le textfield, il faut forcer le endEditing avec:

    [window makeFirstResponder:nil];


  • lugdanumlugdanum Membre
    13:50 modifié #3
    Bonsoir

    J'avais déjà  essayé avec ça mais sans succès.

    En fait c'est plus après la perte du focus je pense que la sauvegarde se fait.

    Merci en tout cas.
  • chkdskschkdsks Membre
    février 2011 modifié #4
    Essayez :o

    1. [tt][AfficheChemin validateEditing];[/tt] après setStringValue:
    2. Modifier directement le DataModel avec un setter, la vue devrait se mettre à  jour toute seule, bindings / Core Data ?
    3. Ou alors si ça ne marche toujours pas, peut être qu'il faut regarder du côté des notifications...
  • lugdanumlugdanum Membre
    13:50 modifié #5
    Bonjour

    Avant tout merci pour ces solutions.

    1. [AfficheChemin validateEditing]; après setStringValue:
    --> Ne fonctionne pas non plus

    3. Ou alors si ça ne marche toujours pas, peut être qu'il faut regarder du côté des notifications...
    --> J'ai essayé avec :

    -(void)awakeFromNib {<br />	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChange:)&nbsp; name:NSControlTextDidChangeNotification object:AfficheChemin];<br />}<br /><br /><br />- (void)textDidChange:(NSNotification *)aNotification<br />{<br />	<br />	NSLog(@&quot;Texte modifié: &quot;);<br />	if([aNotification object] == AfficheChemin)<br />	{<br />		NSLog(@&quot;Texte modifié dans le bon&quot;);<br />	}<br />}
    


    Mais ça ne fonctionne pas non plus, avec "controlTextDidChange" non plus

    2. Modifier directement le DataModel avec un setter, la vue devrait se mettre à  jour toute seule, bindings / Core Data ?
    -->Je ne sais pas encore faire cela, je vais me documenter et essayer.

    Encore merci en tout cas !
  • chkdskschkdsks Membre
    février 2011 modifié #6
    Pour les notifications :

    [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:NSControlTextDidChangeNotification object:AfficheChemin]];
    


    Avec :
    - (void)controlTextDidChange:(NSNotification *)aNotification
    


    Et connecter le delegate.
  • lugdanumlugdanum Membre
    13:50 modifié #7
    Bonsoir

    Merci, merci, au moins j'ai mon NSLog qui s'affiche.

    donc en faisant :
    <br />[[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:NSControlTextDidChangeNotification object:AfficheChemin]];
    


    et

    - (void)controlTextDidChange:(NSNotification *)aNotification<br />{<br />	<br />	NSLog(@&quot;Texte modifié: &quot;);<br />	if([aNotification object] == AfficheChemin)<br />	{<br />		NSLog(@&quot;Texte modifié dans le bon&quot;);<br />	}<br />		<br />}
    


    J'ai bien "Texte modifié:" et "Texte modifié dans le bon" qui apparaà®t dans ma console, par contre la sauvegarde ne se fait toujours pas, sniff.

    Quand je colle du texte dedans, c'est la même chose, la sauvegarde n'a pas lieu, par contre dès que je tape du texte "manuellement" au clavier dedans, la sauvegarde à  bien lieu.

    En tout cas j'ai encore appris quelque chose ce soir grâce à  toi.

    Il doit me manquer pas grand chose j'imagine, mais il faut que je trouve quoi...

    Merci.
  • mpergandmpergand Membre
    13:50 modifié #8
    Mais pour la sauvegarde, tu utilises les bindings ? CoreData ?

    Sinon, pour que ton controller reçoive les notifications, il suffit qu'il soit délégate du TextField:

    [AfficheChemin setDelegate:leController];
  • lugdanumlugdanum Membre
    13:50 modifié #9
    Je vais finir pas te fatiguer.... :(

    En fait je me suis basé sur cet exercice : http://cocoadevcentral.com/articles/000085.php

    Et par exemple pour le champ (dans leur exercice) "Title", j'ai juste rajouter ce fameux bouton qui permet de choisir un dossier.

    VOilà , merci de prendre (ou perdre) du temps pour m'aider.
    :)
  • mpergandmpergand Membre
    février 2011 modifié #10
    Je n'y connais rien  en CoreData ...

    Essaye:
    <br />	<br />if([openPanel runModal] == NSFileHandlingPanelOKButton)<br />{<br />&nbsp; [self willChangeValueForKey:@&quot;KeyPourLeChemin&quot;]; <br />&nbsp; [AfficheChemin setStringValue:[[openPanel URL] path]];<br />&nbsp; [self didChangeValueForKey:@&quot;KeyPourLeChemin]; <br />}<br />
    


    Sinon, fais une recherche sur ce forum, ce problème a déjà  été évoqué.
  • lugdanumlugdanum Membre
    13:50 modifié #11
    Bonsoir


    J'avais bien essayé avec ce même code :

    [self willChangeValueForKey:@&quot;CheminFichier&quot;]; <br />[AfficheChemin setStringValue:[[openPanel URL] path]];<br />[self didChangeValueForKey:@&quot;CheminFichier&quot;];
    


    Ou CheminFichier est la clef, mais cela ne fonctionne pas non plus.
    Enfin ça fonctionne qu'à  moitié, si on tappe au clavier dans le champ c'est ok, mais les copier/coller ou le path du NSOpenPanel ne sont pas pris en compte.

    Je vais continuer mes recherches.


    Merci beaucoup !
    <3
  • chkdskschkdsks Membre
    février 2011 modifié #12
    Il faut que tu nous donnes ce que tu as mis dans les bindings pour ton champ, si tu utilises un objet modèle qui supporte KVC (@property et @synthesize ?).

    <a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueCoding/Concepts/Overview.html#//apple_ref/doc/uid/20001838-SW1&quot;&gt;Documentation Key-Value Coding</a>

    Dans ce cas, modifie la valeur de ton modèle directement pour voir si ça se répercute (architecture MVC).
  • laudemalaudema Membre
    février 2011 modifié #13
    Tu peux regarder dans IB sur quelle action le message d'action est envoyé, il y a 2 solutions: "Sent on End Editing" et Sent on Enter Only.
    Si tu es en enter only ça pourrait expliquer.

    Et pourquoi ne pas utiliser ton "modèle" ?
    Si tu as lié ton AfficheChemin à  un path c'est que tu veux utiliser ce chemin je suppose et donc qu'il est un "membre" de ton objet ?
    Dans ce cas plutôt que de chercher à  valider depuis ton TextField (qui s'occupe surtout de ce que l'utilisateur entre au clavier) pourquoi ne pas lier la valeur de ton textField à  cette variable (dans ton cas, si tu as suivi l'exemple donné en lien, de ta propriété CoreData) et quand tu récupères le chemin tu affectes ça à  ta propriété et Cocoa mettra à  jour ton champ texte.

    [Edit: ce que te proposes chkdsks en fait]
  • lugdanumlugdanum Membre
    13:50 modifié #14
    Bonsoir

    Merci vraiment pour vos réponses.
    Je pense que le problème vient de moi, je n'y arrive pas c'est tout.

    A l'occasion si vous avez le temps, j'ai modifié un chouya l'exemple pour vous montrer, mais franchement ne perdez pas du temps la dessus car je vais abandonner je pense, j'ai encore pas mal de choses à  étudier pour progresser ! Autant maintenant la programmation Iphone/Ipad me parle un peu mais OSX .... :(

    Merci.
  • laudemalaudema Membre
    février 2011 modifié #15
    dans 1298407690:

    dans 1298407690:

    Je pense que le problème vient de moi, je n'y arrive pas c'est tout.

    Si ça peut te rassurer je n'y suis pas arrivé non plus  :D ! Mais je crois que je sais pourquoi: à  la base un NSTextField est fait pour entrer dans ton modèle des valeurs que l'utilisateur entre au clavier.
    Pour ça il est très bien et l'appui sur les touches déclenche les actions pertinentes dans Cocoa. Par contre le modifier par programmation n'a pas de sens dans ce cas là : il faudra que ton utilisateur frappe sur  [tabulation | retour chariot | entrée] pour que AppKit détecte la modification et la répercute. Rien ne semble prévu (à  dessein ?) pour que ça se fasse autrement.

    dans 1298407690:

    Autant maintenant la programmation Iphone/Ipad me parle un peu mais OSX .... :(

    À la limite OSX n'a rien à  voir dans tout cela, si Cocoa est porté un jour pour linux ou BSD ou Windows (s'il existe encore ce jour là  ;) tu retrouveras les mêmes problèmes.
    Si tu regardes dans le dossier Frameworks de ton application tu y verras deux sous dossiers, si tu cliques sur le dossier Linked Frameworks tu y verra le seul Cocoa et dans Other Frameworks AppKit, Foundation et CoreData. Si tu regardes le header de Cocoa tu verras qu'il importe les 3 autres.. Cocoa c'est AppKit & Foundation & CoreData
    Il semble que tu confondes Cocoa et AppKit, AppKit se charge de l'interface utilisateur dans Cocoa mais ce qui fait le travail en dessous c'est Foundation et CoreData.
    http://fr.wikipedia.org/wiki/Cocoa_(Apple)#Framework_principal

    Or tu modifies le texte contenu dans un contrôle de AppKit en espérant que ça va faire comme si l'utilisateur l'avait fait avec le clavier et que ça va changer la valeur de ... Nulle trace dans ton code que tu veuilles changer cheminFichier ! Et AppKit ne répercutera pas le changement tant que ton utilisateur ne l'aura pas validé en appuyant sur Enter ou Tabulation ou Retour Chariot, qui sont interprétés comme fin de saisie car tu es dans un NSTextField et Cocoa/AppKit utilise le fieldEditor de la fenêtre pour être capable de déduire ça...

    Le plus simple, si tu veux y arriver, est de récupérer une référence sur le NSArrayController "posts" qui est dans ton nib. Lui sait quel post tu as choisi dans la liste de ta VueTableau et par lui tu pourras changer les données du modèle (et, du coup, de la vue qui lui est associée). Le chemin inverse de celui que tu as pris mais le chemin que Cocoa s'attend à  te voir prendre.

    Avec Cocoa les choses simples sont simples, les choses compliquées sont possibles


    Si une chose simple est compliquée à  réaliser c'est que je m'y suis mal pris

    Pas besoin de créer une variable URL ni de se soucier du NSTextField, encore moins du bouton d'ailleurs (juste de la méthode qui sera déclenchée par lui).
    <br />//&nbsp; BlogDemoAppDelegate.h<br />//&nbsp; BlogDemo<br />//<br />//&nbsp; Created by Scott Stevenson on 4/11/05.<br />//&nbsp; Copyright __MyCompanyName__ 2005 . All rights reserved.<br /><br />#import &lt;Cocoa/Cocoa.h&gt;<br /><br />@interface BlogDemoAppDelegate : NSObject &lt;NSTextFieldDelegate&gt;<br />{<br />&nbsp; &nbsp; IBOutlet NSWindow *window;<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; NSManagedObjectModel *managedObjectModel;<br />&nbsp; &nbsp; NSManagedObjectContext *managedObjectContext;<br />	<br />&nbsp; &nbsp; IBOutlet NSArrayController *postsController; //A connecter dans mainMenu.nib<br />	<br />}<br /><br />- (NSManagedObjectModel *)managedObjectModel;<br />- (NSManagedObjectContext *)managedObjectContext;<br /><br />- (IBAction)saveAction:sender;<br /><br />- (IBAction)AFFICHELECHEMIN:sender; //Serait plus &quot;conventionnelle&quot; si elle était écrite: -(IBAction) afficheLeChemin:(id)sender;<br /><br />@end<br />
    

    Pas besoin de créer l'objet postsController: ce sera celui créé par AppKit au lancement de l'application au désarchivage du .nib. Une fois en sa possession tu peux accéder à  sa propriété selection qui est un proxy pour une entité Post telle que définie dans ton modèle. Ton code devient alors
    <br />- (IBAction)AFFICHELECHEMIN:(id)sender{	<br />	NSOpenPanel *openPanel = [NSOpenPanel openPanel];<br />	[openPanel setCanChooseDirectories:YES];	<br />	if([openPanel runModal] == NSFileHandlingPanelOKButton){<br />		[[postsController selection] setValue:[[openPanel URL] path] forKey:@&quot;cheminfichier&quot;];<br />	}	<br />}<br />
    

    De cette manière tu modifies l'attribut de ton modèle et la modification, répercutée dans la vue, sera bien prise en compte par CoreData et sera sauvegardée..

    dans 1298407690:

    Merci.

    De rien. Un peu de lecture ?
    Les fondamentaux (en anglais) de Cocoa

    hth
  • lugdanumlugdanum Membre
    13:50 modifié #16
    Bonjour

    Et bien que dire à  part ... Respect ! Expliqué comme cela, c'est tout de suite plus compréhensible !

    Evidemment maintenant ça fonctionne.


    Je vais me replonger dans la lecture, j'en ai bien besoin effectivement, et continuer les tutoriels ...

    En tout cas encore un GRAND MERCI pour toutes ces explications !!
    o:)
  • chkdskschkdsks Membre
    février 2011 modifié #17
    Tu peux désactiver le bouton pour le chemin de fichier quand il n'y a pas de sélection, avec un binding sur Enabled.
    [tt]
    Bind to: Posts
    Controller Key: selection
    Model Key Path: title
    Value Transformer: NSIsNotNil
    [/tt]
    J'ai pris title parce qu'il est obligatoire.

    :)

    Bonne journée
  • lugdanumlugdanum Membre
    13:50 modifié #18
    Ah oui, excellent ! Merci !
    ::)
  • laudemalaudema Membre
    13:50 modifié #19
    Deux livres en français, si tu veux investir du temps (et un peu d'argent quand même) pour appréhender Cocoa
    Programmation Cocoa sous Mac OS X
    De Aaron Hillegass, une bonne base à  AppKit et ses rapports avec Foundation
    Et Les design patterns de Cocoa
    Ouvrage de Erik M. Buck et Donald A. Yacktman bien traduit aussi qui permet de mieux comprendre ce qu'il y a derrière les objets de Cocoa et comment ils s'articulent les uns les autres.

    NB: les lliens sur Pearson car il n'y a pas qu'Amazon et en plus on peut acheter un pdf à  peine moins cher que le livre papier mais qui a ses charmes aussi (en particulier pour la recherche et les images/schémas)
  • lugdanumlugdanum Membre
    13:50 modifié #20
    Oui, il va bien falloir que j'investisse dans ce genre de livre.
    Je ne connaissais pas Pearson, c'est vrai que pour le coup je préfère en PDF aussi, je peux lire après même sur mon ipad et ça le fait moins au travail si je me fait attraper avec un livre à  la mian, tandis que devant un écran (un alt+tab se fait vite sur Windows...)  ;)

    Je pense que certaines personnes sur ce forum devraient se réunir pour nous concocter un livre car elles ont largement les compétences !
    Pourquoi pas sous forme de PDF aussi, une partie de l'argent serait pour les auteurs et l'autre pourrait servir également pour investir dans le site ?

    Merci encore pour tout !
    :)
  • dom123dom123 Membre
    13:50 modifié #21
    Bonjour,

    Je me présente je m'appele dominique je suis nouveau sur le forum et j'ai un souci je ne trouve pas ou poster un sujet de discussion,
    je suis désolé je me suis permis de poster ici car j'ai une seconde  question concernant les NsTextField,

    Je me sers depuis peu de xcode et interface builder et dans une doc sur un forum on me dit d'inserer un UILabel mais je
    ne trouve à  aucun endroit dans interface builder de uilabel je n'ai que des objets commencant par NS...
    J'ai donc des NsTextField mais pas de UI quelquechode dans le module library
    Si quelqu'un pouvait éclairer ma lanterne concernant mes deux questions

    Merci par avance
    Cordialement
    Dominique
  • laudemalaudema Membre
    mars 2011 modifié #22
    Probable que tu te sois trompé de forum les UIQKekChoz sont pour iOS et pas Mac OS et aussi que tu n'as pas installé le bon environnement de programmation mais je laisse plus averti que moi te répondre sur un de ces forums.

    Pour poster dans le bon forum tu peux cliquer sur le lien "Communauté" en haut à  gauche de chaque page qui te mène à  la racine des groupes classés par thèmes. Si tu veux utiliser des UILabel(s) tu as les groupes Développement iOS SDK (iPhone/iPad). Je les fréquente peu mais le plus approprié est probablement Developer programs, déploiement, devices... .

    Quelque soit le groupe où tu atterris après l'avoir choisi tu as toujours un bouton rouge Nouveau sujet (en fait en blanc sur fond rouge) au dessus de la barre noire entête de la liste des sujets. Y'a puka :)

    Oups, j'allais oublier: n'hésite pas à  te présenter dans le forum "Nouveaux membres" et d'offrir une tournée de Perrier Citron (ça n'est pas obligatoire, d'autres boissons sont aussi très appréciées, mais bon, tu auras été prévenu ;)
Connectez-vous ou Inscrivez-vous pour répondre.