Bindings et suppression d'objets

olofolof Membre
20:49 modifié dans API AppKit #1
'jour !

J'ai un problème avec la suppression d'objet dans un tableau. Je vais essayer d'être clair, mais ça va pas être simple.

Mon appli, une gestion de cave à  vin. Dans mon modèle, un objet FGCave (ma cave, qui contient un nom, un nombre de bouteilles restantes et un tableau), un objet FGVin (un nom, un millésime, un nombre de bouteilles restantes, ...). Vous l'aurez compris, le tableau de mon objet FGCave contient des instances de FGVin.

J'ai un controller qui porte le joli nom de CaveDoc. Avant, tout se passait (bien) sans bindings. Maintenant, je suis en train de remplacer tous ces glue-code par les bindings.
J'ai un NSObjectController dont l'outlet 'content' est relié à  mon controller CaveDoc. Ca me permet d'afficher à  l'écran des données de ma cave (nom, nb bouteilles restantes, ...).
J'ai un NSArrayController pour gérer l'affichage des vins de la cave. 'Object Class Name' de ce controller est FGVin. Ce controller est bindé à  mon NSObjectController vu juste plus haut et le model key path est cave.bouteilles (cave -> FGCave et bouteilles et le tableau de FGVin).
Les colonnes de ma table view sont bindé au NSArrayController et le model key path est simplement le nom de l'attribut de l'objet NSVin.

Pour l'affichage, tout va bien. Mon problème est à  la suppression de vins. J'ai un bouton qui déclenche une action. Cette dernière demande confirmation et fait appelle la méthode -remove de mon NSArrayController. Jusque là , c'est parfait, l'instance sélectionnée disparaà®t de ma table view. Le problème est que le nombre de bouteilles restantes (attribut de mon objet FGCave), lui, ne change pas. Comment faire ? J'ai essayé de mettre en place une "observation" avec la méthode -setKeys: triggerChangeNotificationsForDependentKey, mais je dis dire que je suis un peu perdu dans la syntaxe des key paths.

Je ne suis pas sur d'avoir été très clair... Si il faut plus d'infos, dites-moi ! Et si quelqu'un a une piste, une idée, ça sera ma tournée !

Merci !

Réponses

  • olofolof Membre
    20:49 modifié #2
    Ou alors, y'a-t-il un moyen de détecter la suppression d'un vin dans le tableau au niveau de l'objet FGCave ?
  • Philippe49Philippe49 Membre
    20:49 modifié #3
    dans 1194797196:


    J'ai un controller qui porte le joli nom de CaveDoc. ...
    J'ai un NSObjectController dont l'outlet 'content' est relié à  mon controller CaveDoc. Ca me permet d'afficher à  l'écran des données de ma cave (nom, nb bouteilles restantes, ...).
    J'ai un NSArrayController pour gérer l'affichage des vins de la cave. 'Object Class Name' de ce controller est FGVin. Ce controller est bindé à  mon NSObjectController vu juste plus haut et le model key path est cave.bouteilles (cave -> FGCave et bouteilles et le tableau de FGVin).
    Les colonnes de ma table view sont bindé au NSArrayController et le model key path est simplement le nom de l'attribut de l'objet NSVin.


    Tu as essayé en bindant le NSArrayController directement avec l'instance bouteilles de CaveDoc sans passer par le NSObjectController (est-il vraiment utile cette intermédiaire ?) 
  • olofolof Membre
    20:49 modifié #4
    En effet, il n'est peut-être pas nécessaire. Mais le résultat est le même en bindant directement le NSArrayContoller à  l'instance de CaveDoc et en utilisant cave.bouteilles comme model key path.
  • Philippe49Philippe49 Membre
    20:49 modifié #5
    Donc CaveDoc est de type FGCave
    et le binding a lieu avec la variable bouteille de CaveDoc
    si cela se passe bien entre ta vue et ton modèle-contrôleur, c'est [bouteille count] qui change, pas le nombre de bouteilles qui d'après ce que j'ai compris est une autre variable.

    Si tu veux que cela fonctionne, il faut donc binder cette variable avec le nombre d'éléments dans la (NSArray) bouteille.
    [self bind:@nbreBouteille toObject: ....

    Fait une recherche dans la doc full-text sur l'utilisation de @count


  • olofolof Membre
    20:49 modifié #6
    Pas exactement.

    CaveDoc, c'est de type NSDocument. CaveDoc contient une instance de FGCave (cave) qui elle même contient un tableau de FGVin.

    La variable bouteille n'existe pas, il s'agit de bouteilles. C'est le tableau de FGVin.

    Par contre, le nombre de bouteilles ne peut pas être trouvé avec @count car une instance de FGVin peut contenir plusieurs bouteilles (FGVin a un attribut nbBouteillesRestantes).
  • Philippe49Philippe49 Membre
    20:49 modifié #7
    dans 1194806873:

    Pas exactement.

    CaveDoc, c'est de type NSDocument. CaveDoc contient une instance de FGCave (cave) qui elle même contient un tableau de FGVin.

    La variable bouteille n'existe pas, il s'agit de bouteilles. C'est le tableau de FGVin.

    Par contre, le nombre de bouteilles ne peut pas être trouvé avec @count car une instance de FGVin peut contenir plusieurs bouteilles (FGVin a un attribut nbBouteillesRestantes).


    Résumons : ton action sur la table view change bouteilles via le NSArrayController, et tu veux que ce changement réalise une action sur une autre variable de CaveDoc qui représente la somme des variables nbBouteillesRestantes de chaque instance FGVin.

    L'utilisation de @sum ressemble bigrement à  ton problème

    The @sum operator returns the total of adding the NSNumber objects returned by sending valueForKeyPath: to each item in the receiver array, with the key path to the right of the array operator as the parameter. Each number is converted to a double and an instance of NSNumber containing the total sum is returned.

    The following example returns the sum of all transactions for the savings account.

    [savingsAccount valueForKeyPath:@transactions.@sum.amount"]



    Sinon tu as toujours la possibilité de faire ton propre code pour -(void) setBouteilles:(NSArray*) aBouteilles; et d'y inclure la mise à  jour du décompte global de bouteilles.

    Que d'histoires pour une bouteille de plus ou de moins !! :)

  • Philippe49Philippe49 Membre
    20:49 modifié #8
    Ceci dit , ton action dans l'interface est sensée supprimer une bouteille ou une catégorie de vin ?
  • olofolof Membre
    20:49 modifié #9
    Merci Philippe !

    Pour finir, je calcule mon nombre de bouteilles dans la méthode setBouteilles (j'ai aussi d'autres choses à  calculer, j'en profite). C'est là  qu'on voit que tout ce qui tourne autour du key-value coding n'est pas encore complètement clair pour moi !

    Je ne savais pas qu'il existait d'autres "types de calcul" comme @count. Mais de toute façon, comme le nombre de bouteilles restantes est un attribut de ma classe FGCave, il faut bien que je le recalcule !  Le @sum ne me convient donc pas dans ce cas précis.


    En tout cas, merci beaucoup. Et comme on parle de bouteilles, tu l'as bien mérité :  :p :p :p :p

    Et pour répondre à  ta dernière question, mon action ne supprime pas une bouteille, mais vin (qui correspond à  un lot de bouteilles). Si tout ça t'intéresse, la version précédente de mon appli (qui fonctionne, pas comme celle qui est en cours) est dispo ici : http://www.olofweb.com/olosoft/gestcave.html
  • Philippe49Philippe49 Membre
    20:49 modifié #10
    dans 1194815882:

    Et comme on parle de bouteilles, tu l'as bien mérité :  :p :p         :p


    voilà  j'ai déjà  supprimé la troisième, et je me la suis mise derrière la table viou ..

    Voilà  un petit code pour utiliser @sum :
    <br />/* main.c */<br />#import &lt;Cocoa/Cocoa.h&gt;<br /><br />@interface FGVin : NSObject {<br />	NSString * nom;<br />	int number;<br />	}	<br />-(id) initWithString:(NSString *) string number:(int) N;<br />@end<br /><br />@implementation FGVin <br /><br />-(id) initWithString:(NSString *) string number:(int) N<br />{<br />	self=[super init];<br />	if(self){<br />		nom=[string copy];<br />		number=N;<br />	}<br />	return self;<br />}<br />-(void) dealloc<br />{<br />	[nom release];<br />	[super dealloc];<br />}<br />@end<br /><br />int main (int argc, const char * argv&#91;])<br />{<br />	NSAutoreleasePool * pool=[[NSAutoreleasePool alloc] init];	<br />	NSArray* a1=[[[FGVin alloc] initWithString:@&quot;a1&quot; number:100] autorelease];<br />	NSArray* a2=[[[FGVin alloc] initWithString:@&quot;a2&quot; number:200] autorelease];<br />	NSArray* a3=[[[FGVin alloc] initWithString:@&quot;a3&quot; number:50] autorelease];	<br />	<br />	<br />	NSArray * cave=[NSArray arrayWithObjects:a1,a2,a3,nil]; <br />	NSNumber * total= [NSNumber numberWithInt:0];<br />	NSDictionary * dico=[NSDictionary dictionaryWithObjectsAndKeys:cave,@&quot;maCave&quot;,total,@&quot;nbBouteilles&quot;,nil];<br />	NSLog(@&quot;%@&quot;,dico);	<br />	NSLog(@&quot;%@&quot;,[dico valueForKeyPath:@&quot;maCave.@sum.number&quot;] ); <br />	[pool release];<br />	return 0;<br />}<br />
    


    à  essayer sans modération  :p   :p

    % gcc pgm.m -o pgm -framework cocoa
    % pgm

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