CoreData : le contraire de setKeys:triggerChangeNotificationsForDependentKey: ?

cargocargo Membre
09:58 modifié dans API AppKit #1
Je ne veux justement pas qu'une propriété soit informée des changements d'une autre !
- soit une entité a (custom class), et sa relation many-to-one avec une entité b
- la valeur d'une property dans a est donnée par un calcul impliquant une property dans b
- cette valeur doit être calculée une fois pour toutes à  un instant t (au moment de la création d'un nouveau "record" dans a) et ne plus dépendre par la suite des différents changements de la property de b.

J'ai lu et relu la doc apple KVC/KVO. J'ai donc essayé d'implémenter dans ma custom class ceci :
http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueObserving/index.html#//apple_ref/doc/uid/10000177i

<br />+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)theKey {<br />BOOL automatic = NO;<br /> <br />&nbsp; &nbsp; if ([theKey isEqualToString:@&quot;propertyB&quot;]) {<br />&nbsp; &nbsp; &nbsp; &nbsp; automatic=NO;<br />&nbsp; &nbsp; } else {<br />&nbsp; &nbsp; &nbsp; &nbsp; automatic=[super automaticallyNotifiesObserversForKey:theKey];<br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; return automatic;<br />}<br />


Mais ça ne fonctionne pas : a change toujours de valeur quand on modifie b, même en faisant un save avant la modif.

Une piste ???

Réponses

  • cargocargo Membre
    09:58 modifié #2
    Bon j'ai deux autres idées :
    - (void)setObservationInfo:(void *)value
    utiliser ça en mettant comme info "nil" mais je comprends pas si l'observationinfo est l'observation que le receiver observe ou que le receiver fournit aux autres objets...

    ou alors

    - (void)awakeFromInsert qui me parait plus réaliste mais l'instance n'aura pas l'info de la relationship au moment de sa création (click sur Add), elle est fournie par l'utilisateur avec un popup qui rapatrie les properties de l'entity b.

    >bon, j'arrête de parler dans le vide et j'essaye
  • cargocargo Membre
    09:58 modifié #3
    C'est bien ce qui me semblait avec awakeFromInsert il me retourne 0 parce qu'à  ce moment là  il n'a pas la valeur...Il faudrait la fournir au moment du click sur Add.
  • cargocargo Membre
    mars 2006 modifié #4
    :why?: :why?: :why?:

    Je ne m'en sors pas là . Je ne vois pas comment faire. Récupérer une donnée à  l'autre bout d'une relationship lors de la création d'une instance d'un objet, la stocker et la mettre hors circuit pour qu'elle ne soit plus mise à  jour par la suite.
    La seule solution c'est awakeFromInsert : ça marche si je lui fournis une constante mais si je lui propose le keypath de la relationship il ne va pas chercher la valeur.
    Je suppose qu'au stade d'awakeFromInit l'instance n'est pas "consciente" de la relationship et de l'objet qui lui est associé.
  • Eddy58Eddy58 Membre
    mars 2006 modifié #5
    La doc dit que quand on surcharge la méthode automaticallyNotifiesObserversForKey, il faut aussi écrire l'accesseur des keys que l'on met en "manual observer notification" en invoquant les méthodes KVO nécessaires aux notifications de changement de valeur. Le code ci-dessous est juste le point de démarrage que j'utiliserais, ensuite je pense qu'il faut trouver comment paramétrer correctement les deux appels de notification pour qu'ils ne prennent en compte que la nouvelle entrée.
    [tt]
    -(void)setPropertyA:(int)newValue
    {
        [self willChange:NSKeyValueChangeInsertion valuesAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(newObjectIndex,1) forKey:@propertyA];
        propertyA=newValue;
        [self didChange:NSKeyValueChangeInsertion valuesAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(newObjectIndex,1) forKey:@propertyA];
    }
    [/tt]
    Sinon, je pense que ce sujet n'est vraiment pas à  sa place dans le forum débutants.... :o
  • cargocargo Membre
    mars 2006 modifié #6
    Le sujet non mais moi oui  :)

    Tu penses que c'est la bonne piste de désactiver les notifications en fait ?
    Le problème ça risque d'être la première entrée, le premier fetch en fait parce qu'au moment de la création de l'objet (Add) la valeur est nulle: c'est suite au choix dans un pop-up que la valeur est rapatriée.
    En plus je me perds dans ces histoire d'observers je ne sais plus finalement dans quelle classe implanter cette méthode : dans la source ou dans l'arrivée ?
    A mon avis la solution c'est awakeFromInsert ou alors l'init de l'objet.

    De plus je ne comprends pas pourquoi il faut implémenter les keys puisqu'on en veut pas justement, ou alors c'est les accessors pour que A puisse signaler ses changement aux autres ? Le willChange c'est un message envoyé aux autres observers ?

    Et pour finir je n'ai pas compris l'histoire à  propos du NSManagedContext qui override de toutes façons la méthode de notification quand on fait une custom class. Ah tiens au fait j'ai crée ma custom class avec l'assistant en décochant accessor methods mais je comprends pas bien non plus à  quoi correspond ce choix.

    Et pour info c'est un projet CoreData document-based
  • cargocargo Membre
    09:58 modifié #7
    J'ai encore réfléchi (ça fume ...).
    En fait il faut lui fournir la bonne valeur, la valeur "actuelle" au moment du runtime.
    Un click sur un contrôle, le calcul se fait par "quelqu'un d'autre" (et là  on peut utiliser le keyPath puisqu'à  l'autre bout il y a la valeur qu'on veut), et le nombre est fourni à  la custom class avec un setPrimitiveValue:forKey:
  • cargocargo Membre
    09:58 modifié #8
    Bon je crois que la solution est ailleurs...
    La solution est dans awakeFromInsert, c'est certain. Tout le "network" CoreData est conçu pour assurer la mise à  jour des valeurs liées, je pense qu'il ne faut pas toucher au KVO si ce n'est pas indispensable.
    Pour stocker des valeurs tels que la date de création par ex, la doc précise que awakeFromInsert est la solution. Il est ainsi utilisé pour l'IDgenerator de Iclass (exemple Xcode).
    Mon problème à  moi est que je n'ai pas la valeur voulue à  ce moment là . A moi de la lui fournir.

    Le life-cycle d'un managedObject est le suivant (d'après ce que j'ai compris):
    - awakeFromInsert > appelé une seule fois, la première fois que l'objet est inséré dans un moc (naissance de l'objet si on peux dire)
    - initWithEntity:insertIntoManagedObjectContex > appelé à  chaque fois que l'objet est instancié, donc à  la création de l'objet mais aussi à  chaque nouvelle ouverture du document par exemple.
    - awakeFromFetch > appelé à  chaque fois que les datas sont rapatriés du persistent store, donc à  l'occasion d'un fetch, d'un refresh etc.

    La valeur que je dois fournir est obtenu d'une manière très standard par un fetch qui associe une instance de A avec une instance de B (choix dans un pop-up menu), donc on se situe bien loin après la création de l'objet.
    La solution est donc de faire une fetch request ou d'aller chercher la valeur par tout autre moyen dans la fonction awakeFromInsert, pour rapatrier à  ce moment là  uniquement la valeur souhaitée.

    J'essaye ça.
Connectez-vous ou Inscrivez-vous pour répondre.