Créer un objet NSManagedObject sans NSEntityDescription

GreensourceGreensource Membre
21:59 modifié dans API AppKit #1
J'ai une petit question. J'ai dans mon modèle Core Data une entity. Cela ma générer une classe qui hérite de NSManagedObject, normal.
En temp normal je créer un nouvel object en faisant:
[NSEntityDescription insertNewObjectForEntityForName:@&quot;MaClass&quot; <br />																		&nbsp;  inManagedObjectContext:managedObjectContext];


Mais là  je voudrais aussi pouvoir créer cet object via le constructeur normal:
MaClass monObjet = [[MaClass alloc] init];


Mais ça ne marche pas du tout, quand j'envois ensuite des message à  monObjet on me répond qu'il ne peut y répondre.

Ma question c'est donc, est-ce que ce que j'essais de faire ne devrais même pas être fait, ou bien est-ce que je le fait mal?

Mon but étant de pouvoir utiliser parfois mes objets sans pour autant les sauver dans Core Data, ou alors pas tout de suite.

Merci & Bonne nuit... o:)

Réponses

  • ClicCoolClicCool Membre
    novembre 2009 modifié #2
    dans 1258845548:
    .../...
    Mon but étant de pouvoir utiliser parfois mes objets sans pour autant les sauver dans Core Data, ou alors pas tout de suite..../...


    Bonne question ça.

    En dehors de NSDictionnary pouvant faire figure de "placeHolders", il me semble que l'usage de NSManagedObject est difficile dans la mesure ou ils doivent avoir un contexte associé pour être "viables".

    Pour ma part donc:
    • Soit j'utilise un NSDictionnary qu'au dernier moment (en général au WillSave) je "transforme" en NSManagedObject que je "rempli" alors avec un [tt]setValuesForKeysWithDictionary[/tt]
    • Soit j'ai besoin de vrais ManagedObjects inclus dans les ArrayControllers et les bindings et alors je crée de vrais ManagedObjects convenablement liés au context et aux autres objects du "graph" mais, qui s'il ne sont pas utilisés seront détruits au prochain appel de willSave (quitte à  en créer d'autres immédiatement après le didSave si ils sont toujours utiles à  l'interface pour que l'utilisateur renseigne leur valeur par ex. )


  • GreensourceGreensource Membre
    novembre 2009 modifié #3
    :'( Holala ça va du tout faire mon affaire ça...
    J'ai pas bien compris ton histoire de "je transforme en NSManagedObject"; Ca signifie que tu as deux classes: MaClassNormale et MaClassManagedObject et qu'au dernier moment tu fait un:
    MaClassManadedObject* monObjetManagé = [NSEntityDescription insertNewObjectForEntityForName:@&quot;MaClassManagedObject&quot; inManagedObjectContext:managedObjectContext];<br />[monObjetManagé setMachin:[monObjetNormal machin];
    

    ?

    [edit] Sinon j'ai une autre idée, je balade mon context partout dans mon appli où j'en ai besoin, mais c'est pas propre il me semble. Sauf que du coup je ne comprends pas non plus comment mes objets pourraient ne pas être sauvegardé, il faut le dire explicitement?
  • ClicCoolClicCool Membre
    21:59 modifié #4
    Dans le cas premier cas que j'ai cité, je ne crée qu'un NSDictionnary que j'utilise via les bindings d'interface.
    Si le managedObject existe il est utilisé sur le bindings, sinon c'est un "bête" dico qui sert de placeHolder qui est bindé.
    A la réception de la Notification WillSave, si le Dico a reçu (via les bindings) des valeurs valides, un ManagedObject est créé et sera sauvegardé. Ses valeurs sont renseignées en une seule passe grace à  [tt]setValuesForKeysWithDictionary:[/tt]
    ResultatManagedObject * resultat = [NSEntityDescription insertNewObjectForEntityForName:@&quot;ResultatManagedObject&quot;<br />							inManagedObjectContext:[self managedObjectContext]];<br />[resultat setValuesForKeysWithDictionary:resultatDico];<br />
    


    Dans le 2 ème cas c'est d'emblé un ManagedObject qui est créé et lors du WillSave, je vérifie qu'il a été renseigné par l'utilisateur, si ce n'est pas le cas je le delete avant que la sauvegarde soit accomplie par le MOContext.
    Dans ces cas là  c'est l'Entité elle même qui implémente le WillSave:
    - (void) willSave {<br />	[super willSave];<br />	if (! self.resultat ) {&nbsp; // si le résultat a été effacé ou non renseigné =&gt; Hara-kiri<br />		if (! [self isDeleted] ){<br />			[[NSNotificationCenter defaultCenter] postNotificationName:@&quot;NotifEntityWillDie&quot; object:self];<br /><br />			[self setBioRslt:nil]; // Retire le lien vers le ManagedObect lié<br />			[[self managedObjectContext] deleteObject: self];<br />		}<br />	}<br />}<br />
    
    L'entité ici poste un notification pour permettre à  l'interface de réagir et d'enventuellement le re-créer par la suite (après le DidSave)


    Sinon, oui, créer un autre Contexte est un solution plus facile dans les cas, par exemple, ou tout se déroule dans une fenêtre (ou sheet) dédiée.
    ça a, en plus, l'avantage de permettre facilement d'enregister les undos possibles sur ces objets.

    PS: j'ai pas bien compris ta dernière phrase.
  • dilarogadilaroga Membre
    21:59 modifié #5
    Citation
    MaClass monObjet = [[MaClass alloc] init];

    Mais ça ne marche pas du tout, quand j'envois ensuite des message à  monObjet on me répond qu'il ne peut y répondre.

    As tu généré les classes de ton modèle de données et implémenté les méthodes que tu as défini graphiquement dans ton modèle ? Si ce n'est pas le cas, ça pourrait provoquer l'erreur que tu rencontres.
    .../...
    Mon but étant de pouvoir utiliser parfois mes objets sans pour autant les sauver dans Core Data, ou alors pas tout de suite..../...

    Une solution pourrait être d'utiliser plusieurs NSPersistantStore pour la gestion de tes données, l'un en mémoire pour tes objets temporaires l'autre ecrit sur le disque pour les données permanentes.


    Sinon j'ai une autre idée, je balade mon context partout dans mon appli où j'en ai besoin, mais c'est pas propre il me semble......

    Tu peux réaliser cette idée proprement, un controller singleton qui est responsable de tes accès aux données; de la gestion de tes persistent stores, de ton context... Comme cela les classes qui en dépendent pourront avoir un lien avec ce controller via son instance partagée.
  • GreensourceGreensource Membre
    21:59 modifié #6
    dans 1258895091:

    As tu généré les classes de ton modèle de données et implémenté les méthodes que tu as défini graphiquement dans ton modèle ? Si ce n'est pas le cas, ça pourrait provoquer l'erreur que tu rencontres.


    Pour certain attribut j'ai juste de @dynamic, ça pourrais être ça? Je vais essayer de changer pour voir.
  • ClicCoolClicCool Membre
    21:59 modifié #7
    dans 1258895091:
    .../...
    .../...
    Mon but étant de pouvoir utiliser parfois mes objets sans pour autant les sauver dans Core Data, ou alors pas tout de suite..../...

    Une solution pourrait être d'utiliser plusieurs NSPersistantStore pour la gestion de tes données, l'un en mémoire pour tes objets temporaires l'autre ecrit sur le disque pour les données permanentes.
    .../...


    Oui, mais pas question de migrer un objet d'un store à  l'autre.
    Faudra le "recopier" dans le bon store et le deleter dans l'autre ... ni si facile ni plus propre comme solution donc.
  • GreensourceGreensource Membre
    21:59 modifié #8
    En fait je ne peut pas implémenter les méthodes que j'ai défini graphiquement, puisque dans la classe que ma créer le .xcdatamodel ya aucun attribut, donc je ne peut pas faire d'accesseur... :(
  • dilarogadilaroga Membre
    21:59 modifié #9
    Faudra le "recopier" dans le bon store et le deleter dans l'autre

    Un travail de gestion qui n'echappe à  aucune des solutions avancées ici. NSDictionary, objets factices, plusieurs stores ils nécessitent tous un minimum de gestion pour basculer les données de l'un à  l'autre.
    ni si facile ni plus propre comme solution donc.

    Elle a l'avantage de ne pas dénaturer dans le code le modèle avec des collections de données intermédiaires qu'il faudra maintenir en parallèle de l'évolution du développement, donc plus de maintenance dans la glue qui rend le code encore un peu moins lisible. De plus, pour les objets temporaires tu peux toujours tirer profit des facilités offertes par CoreData.
  • dilarogadilaroga Membre
    novembre 2009 modifié #10
    En fait je ne peut pas implémenter les méthodes que j'ai défini graphiquement, puisque dans la classe que ma créer le .xcdatamodel ya aucun attribut, donc je ne peut pas faire d'accesseur...

    Arg, tu pourrais surement rajouter les attributs mais faudrait re-implémenter les accesseurs, ça ferait pas mal de boulot en effet... Tu peux toujours utiliser le mécanisme de Key Value Coding.
  • ClicCoolClicCool Membre
    21:59 modifié #11
    dans 1258897051:

    Faudra le "recopier" dans le bon store et le deleter dans l'autre

    Un travail de gestion qui n'echappe à  aucune des solutions avancées ici. NSDictionary, objets factices, plusieurs stores ils nécessitent tous un minimum de gestion pour basculer les données de l'un à  l'autre.

    Absolument



    dans 1258897051:
    .../... De plus, pour les objets temporaires tu peux toujours tirer profit des facilités offertes par CoreData.

    Quelles facilités ?
  • dilarogadilaroga Membre
    21:59 modifié #12
    .../... De plus, pour les objets temporaires tu peux toujours tirer profit des facilités offertes par CoreData.
    Quelles facilités ?

    Celles que peuvent apporter une bibliothèque de persistence de données. Par exemple, si  tu veux optimiser ton code pour un gain de performance (utilisation des ressources mémoires) dans le cas où l'on manipule beaucoup d'objets temporaires (ça peut être embêtant sur certaines plateformes comme iPhone OS) on peut très facilement stocker les objets temporaires sur le disque en changeant le mode du peristent store et dans ce cas tirer profit d'un chargement de tes objets à  la demande.
  • ClicCoolClicCool Membre
    21:59 modifié #13
    Je vois toujours pas de quoi, précisément, tu parles  :-\\

    dans 1258905908:
    .../... une bibliothèque de persistence de données.

    ?

    dans 1258905908:
    .../... on peut très facilement stocker les objets temporaires sur le disque en changeant le mode du peristent store et dans ce cas tirer profit d'un chargement de tes objets à  la demande.

    Là  tu fais allusion au type SQLLite ?
    Ou un type de strore perso ?
  • dilarogadilaroga Membre
    21:59 modifié #14
    .../... une bibliothèque de persistence de données.

    Un mécanisme de sauvegarde et de restauration des données. Pour enregistrer un objet il faut le mettre en relation avec une structure de données persistante (un fichier plat, xml, sqlite, sql, etc...). Le but d'une telle bibliothèque est de faire correspondre deux modèles différents: le modèle objet et le modèle de peristance.

    Là  tu fais allusion au type SQLLite ?
    Ou un type de strore perso ?

    sqlite plus précisément. Mais c'est vrai, si on est motivé, on peut créer son propre store.
  • GreensourceGreensource Membre
    21:59 modifié #15
    Bien, merci pour toute vos solutions.
    Je crois que je vais retenir la suivante:
    - Faire un singleton qui me donne accès à  la Core Data Stack, notamment la récupération du managedObjectContext.
    - Ensuite je pourrais créer mes objets n'importe où.

    Je vais peut-être même modifier la méthode init de mon objet pour dedans faire l'appel:
    [NSEntityDescription insertNewObjectForEntityForName:@&quot;MaClassManagedObject&quot; inManagedObjectContext:managedObjectContext]
    

    Mais je j'ai peur que Core Data fasse déjà  à  un moment ou un autre appel à  init de l'objet doc j'ai peur que ça foute la zone. Je vais essayer.
  • ClicCoolClicCool Membre
    21:59 modifié #16
    dans 1258918236:
    .../...
    Je vais peut-être même modifier la méthode init de mon objet pour dedans faire l'appel:
    [NSEntityDescription insertNewObjectForEntityForName:@&quot;MaClassManagedObject&quot; inManagedObjectContext:managedObjectContext]
    

    Mais je j'ai peur que Core Data fasse déjà  à  un moment ou un autre appel à  init de l'objet doc j'ai peur que ça foute la zone. Je vais essayer.


    Oui ça me parait pas terrible du tout comme idée ton init.
Connectez-vous ou Inscrivez-vous pour répondre.