Bindings dans une appli multi-xib

FloFlo Membre
juillet 2008 modifié dans API AppKit #1
Bonjour,

mon problème se situe au niveau du partage de certains objets via NSApp entre plusieurs nib au sein d'une appli coreData. Je m'explique, je dispose de deux fichiers xib :

1er xib :

Créer l'appDelegate (delegate de NSApp) qui référence et initialise le contexte, le persistent store, etc...
L'appDelegate créer également un NSWindowController propriétaire du second xib.

2ieme xib

Créer un certain nombre de controllers... je souhaiterai que ces controllers puissent accéder au context de l'AppDelegate via les bindings afin d'y ajouter, supprimer... des objets.
J'ai donc "bindé" ces controllers à  l'objet NSApplication en utilisant la clé suivante :
delegate.managedObjectContext

Or quand je lance l'appli, il ne se passe rien quand j'essaye d'ajouter des objets dans le contexte via les controllers du second xib. J'ai testé exactement les mêmes connexions dans le premier xib et sa marche... :-\\

Ma question est donc la suivante, comment faire pour rendre accessible le contexte du premier xib au second via les bindings? Ou, précisément, comment connecter les controllers du seconds au contexte de l'AppDelegate du premier via les bindings?

Merci d'avance pour vos réponses.

Réponses

  • Philippe49Philippe49 Membre
    16:57 modifié #2
    Dans le window controller du 2ème xib
    - (void)awakeFromNib
    {
        id appDelegate=[NSApp delegate];
        [appDelegate installBindings:self];
    }

    Dans appDelegate
    -(void) installBindings:(id) sender
    {
        id aNibObject=[sender valueForKey:@objectReference];
        [aNibObject bind: .....
    }

  • FloFlo Membre
    juillet 2008 modifié #3
    Merci, je vais essayer ça...

    N'y a-t-il pas un moyen de faire ce genre de chose via interface builder ?

    Pourquoi ce que je tente de faire ne marche pas ?
  • Philippe49Philippe49 Membre
    juillet 2008 modifié #4
    Ah oui je n'avais pas lu vraiment cete partie de ton post. Ton idée de binding  est intéressante.
    Il s'agit d'un binding avec un intermédiaire : le delegate de NSApp.

    Dans mes essais sur les bindings, je réglais ce genre de problème soit en exposant le binding dans la method +(void) initialize de la classe intermédiaire (ici ton appDelegate), soit en faisant une property de la variable d'instance observée, ici   managedObjectContext.

    Cela semblait régler le problème de "double observation" dans lequel on se trouve.
  • Philippe49Philippe49 Membre
    16:57 modifié #5
    dans 1217179166:

    Pourquoi ce que je tente de faire ne marche pas ?


    Ue seconde question à  se poser, c'est un problème de synchronisation lors du lancement de l'application :
    Est-ce que lors de la mise en place du second xib, les objets du premier sont bien initialisés ?
  • FloFlo Membre
    16:57 modifié #6
    Est-ce que lors de la mise en place du second xib, les objets du premier sont bien initialisés ?


    Excellente question ! J'allais justement la poser...
    Quand je fais un NSLog() du context dans awakeFromNib du NSWindowController je n'ai pas nil en tout cas...

    J'avais essayé en mettant une property style :
    @property(readonly) NSManagedObjectContext *managedObjectContext;
    


    mais sans succès  :-\\
  • FloFlo Membre
    16:57 modifié #7
    En fait, j'initialise le NSWindowController(et donc le second nib) dans la méthode :

    <br />- (void) applicationDidFinishLaunching: (NSNotification*)notification<br />{<br />	NSLog(@&quot;%@&quot;, [self managedObjectContext]);<br /><br />	mainWindowController = [[ITMainWindowController alloc] initWithWindowNibName: APP_MAIN_WINDOW];<br />	[mainWindowController showWindow: self];<br />}<br />
    


    Donc à  ce moment le contexte est initialisé, d'ailleur j'ai

    <br />2008-07-27 21:23:15.620 iTrade[1229:10b] &lt;NSManagedObjectContext: 0x186c70&gt;<br />
    


    dans le log...

    En fait de base, quand on créer une appli coreData, il y a la méthode
    - (NSManagedObjectContext *) managedObjectContext
    dans le .m de l'AppDelegate

    Cette méthode rentre peut-être en conflit avec la property non ?



  • Philippe49Philippe49 Membre
    16:57 modifié #8
    dans 1217187009:

    En fait de base, quand on créer une appli coreData, il y a la méthode
    - (NSManagedObjectContext *) managedObjectContext
    dans le .m de l'AppDelegate
    Cette méthode rentre peut-être en conflit avec la property non ?


    Il faut utiliser alors @dynamic managedObjectContext;
  • Philippe49Philippe49 Membre
    juillet 2008 modifié #9
    Voilà  un essai de binding avec double xib. Cela a l'air de marcher sans problème, tout étant fait dans IB.

    un slider dans le premier xib bindé avec un CGFloat sliderValue dans AppDelegate

    un slider dans le second xib bindé avec le CGFloat sliderValue de l'application delegate
  • FloFlo Membre
    16:57 modifié #10
    Comme le projet de la dernière fois, je ne peux pas compiler celui-la même en changeant la propriété project format du menu get info, j'ai pourtant la version 3.0... (ce qui n'est pas grave puisque chez toi ça fonctionne)

    Je ne comprends pas pourquoi chez moi ça ne marche pas, est-ce que le fait qu'il est question de binder la propriété managedObjectContext d'un controller change quelque chose quand l'on souhaite passer par un objet intermédiaire (l'appDelegate)?

    J'ai essayé le tag @dynamic avec une property(readonly) pour ne fournir qu'un getter mais sans succès... De toute façon je pense que normalement sa devrait fonctionner sans non ?
  • Philippe49Philippe49 Membre
    16:57 modifié #11
    dans 1217252737:

    Comme le projet de la dernière fois, je ne peux pas compiler celui-la même en changeant la propriété project format du menu get info, j'ai pourtant la version 3.0... (ce qui n'est pas grave puisque chez toi ça fonctionne)

    Cela passe mieux comme cela ?

  • FloFlo Membre
    16:57 modifié #12
    Beaucoup mieux merci, mais je ne vois toujours pas pourquoi il m'est impossible de synchroniser mon contexte par le même processus avec l'arrayController du deuxième xib... ???
  • Philippe49Philippe49 Membre
    16:57 modifié #13
    dans 1217252737:

    J'ai essayé le tag @dynamic avec une property(readonly) pour ne fournir qu'un getter mais sans succès... De toute façon je pense que normalement sa devrait fonctionner sans non ?

    A priori, oui.

    Hillegass parle de Core Data au Ch 30 de son livre (L'appli des employés). Il met des properties, et rajoute une méthode qui est
    @property (retain) NSString * firstName;
    @property (retain) NSString * lastName;
    @property (readonly) NSString * fullName;

    +(NSSet*) keyPathsForValuesAffectingFullName
    {
     return [NSSet setWithObjects:@firstName,@lastName,nil];
    }

    Dans les addEmployee ou removeEmployee, il utilise les messages willChangeValueForKey et didChangeValueForKey.





  • Philippe49Philippe49 Membre
    16:57 modifié #14
    dans 1217253967:

    Beaucoup mieux merci, mais je ne vois toujours pas pourquoi il m'est impossible de synchroniser mon contexte par le même processus avec l'arrayController du deuxième xib... ???

    Il y a peut-être une différence de taille entre ton appli et la mienne c'est que mon binding est du type one-to-one, et le tien il y a du many là -dessous (one-to-many ou many-to-many).
  • FloFlo Membre
    16:57 modifié #15
    Je peux peut-être passer la référence du contexte via la méthode setManagedObjectContext: mais c'est moins pratique...

    Il y a peut-être une différence de taille entre ton appli et la mienne c'est que mon binding est du type one-to-one, et le tien il y a du many là -dessous (one-to-many ou many-to-many).


    heu... je suis un peu perdu là , one-to-one, one-to-many et many-to-many ne sont pas plutôt des propriétés de relashionship dans le dataModel ?

    Un objet complexe comme le managedObjectContext ne convient peut-être pas aux bindings par un objet intermédiaire, non ?


  • Philippe49Philippe49 Membre
    16:57 modifié #16
    dans 1217256815:

    heu... je suis un peu perdu là , one-to-one, one-to-many et many-to-many ne sont pas plutôt des propriétés de relashionship dans le dataModel ?


    Ce sont des situations de Key Value Observing. Dans mon appli, un objet observe un autre objet one-to-one.
    La situation est beaucoup plus compliquée lorsqu'un objet observe un tableau, ou lorsqu'un tableau observe un tableau.
  • FloFlo Membre
    16:57 modifié #17
    C'est bon s'est résolu...  :o

    Tu vas rire... encore un problème de localizable de base sur MainMenu.xib quand on le créer via Interface Builder.

    Je ne comprends pas comment ce genre de propriété peut autant perturber la gestion des nibs...

    J'ai changé de méthode car j'ai remarqué que si je met dans chaque nib une tableView avec un ArrayController derrière et que j'utilise NSApp comme objet intermédiaire pour binder le contexte du nib ne contenant pas l'AppDelegate, la synchro des vues prends parfois plusieurs secondes... C'est un petit peu comme si avec tes sliders, quand on en bouge un et bien l'autre prenait plusieurs secondes à  se synchroniser à  la bonne valeur.

    Au final, pour info, je créer une variable context dans le NSWindowController que je fixe dans init
    <br />- (void) init<br />{<br />&nbsp; ...<br />&nbsp; context = [[NSApp delegate] managedObjectContext];<br />&nbsp; ...<br />}<br />
    


    C'est cette variable que je binde a l'ArrayController et plus directement par la clé:
    NSApp.delegate.managedObjectContext

    Cette solution est beaucoup plus optimisée.

    En tout cas merci pour le temps passé à  m'aider à  résoudre mon problème.



Connectez-vous ou Inscrivez-vous pour répondre.