Core Data: creation d'une nouvelle instance dans une table avec une relationship to-Many
Bonjour à Tous,
Voilà je débute en développement iOS, et depuis quelques semaines je développe une application iphone pour une boite espagnol. Dans ma base de donnée local de l'appli, j'ai plusieurs tables ayant des relation to_Many. Et c'est là où j'ai du mal à comprendre le fonctionnement de Core Data...
J'ai enregistré dans la table “TPAC_TipoPaciente†mes types de patients, et je veux enregistrer des patients dans "PAC_Pacientes" et c'est là que ça bloque car je ne comprends pas comment relier un patient à un type de patients spécifique.
Pour l'instant mon code pour insérer une nouvelle instance patient et celui-ci :
NSManagedObjectContext * context = [self managedObjectContext];
PAC_Pacientes *newPaciente= [NSEntityDescription insertNewObjectForEntityForName:@PAC_Pacientes inManagedObjectContext:context];
[newPaciente setValue:@Pedro forKey:@nombre];
[newPaciente setValue:@Muà±oz forKey:@apellido1];
[newPaciente setValue:@Carlos forKey:@apellido2];
TPAC_TipoPaciente *tipo= [NSEntityDescription insertNewObjectForEntityForName:@TPAC_TipoPaciente inManagedObjectContext:context];
[tipo addPacienteObject:newPaciente];
NSError *error;
if (![context save:&error])
{
NSLog(@Erreur lors de l'enregistrement des données: %@ - %@", error, [error userInfo]);
}
Mais ce code ne me relie pas mon patient à mon type "pacientAvecUneMutuel" (par ex.)...
Ce que j'essai de faire, c'est que "tipo_de_pacient" de “PAC_Pacientes†pointe vers l'instance "pacientAvecUneMutuel" de la table "TPAC_TipoPaciente".
Est ce que qu'un peut m'éclairer?
Réponses
il faudrait que l'on puisse voir la déclaration de ton model CoreData
perso, pour signifier que je suis dans une relation 1->n je mettrais un 's' à paciente
Ce que tu fais dans ton code, c'est la création d'un patient ET la création d'un type de patient (tu fais deux insertNewObjectForEntityForName .
Or j'imagine que les types de patient sont déjà renseignés et que tu veux simplement lié un nouveau patient à un type déjà existant. Non ?
Il faut donc que tu créé ton patient et que tu fetch le type de patient adéquat. Ensuite tu peux alors lier les deux.
Par exemple :
Même remarque que xyloweb pour le pluriel des relations to-many (sauf que j'en trave que dalle en espagnol et que je ne sais pas comme on y exprime le pluriel...).
Sinon, perso comme j'utilise l'excellent framework MagicalRecord pour me simplifier CoreData (voir ma présentation CocoaHeads #13 Rennes, qui sort en vidéo demain), j'aurais écris le code de Kub comme ceci :
Ca fait exactement la même chose que le code de Kubernan, mais perso je trouve que MR rend le code plus clair et plus lisible, et en plus évite les risques de fautes de frappes puisque tu ne manipules plus des NSString mais des classes et méthodes, donc l'autocomplétion t'aide et une erreur de frappe est repérée au compile-time. Après tout est affaire de goût.
y m'énerve !
.
.
.
.
.
.
À chaque fois t'arrive à caser ton MR... je suis hilare
Merci Kubernan!!
Oui effectivement, dans mon code je créais à chaque fois une nouvelle instance de TPAC_TipoPaciente... avec un fetch c'est mieux!!
Et je vais rajouter un s à paciente dans ma table, ça sera + claire!! (comme en français! )
Quant à MagicalRecord, effectivement c'est plus rapide...! (bon, je vais déjà faire le tour de CoreData avant de me lancer dans un framework!)
Encore une petite question..., comment je peux faire pour connaitre la valeur du "type de patient" à partir d'une instance "patient"?
Par exemple, mon code est celui ci:
Comment fait on pour acceder à la valeur de l'attribut "descripcion" (de la table TipoPaciente) de "unPaciente"?
Voilou! muchas gracias!!!
Ps: ok AliGator, je vais me presenter sur le "Présentation des Membres"!
Perso quand j'ai voulu me mettre à CoreData, quand j'ai vu la complexité du framework CoreData j'ai fait demi-tour tout de suite. Trop de classes nouvelles de partout, des NSPersistentStore des NSFetchRequest des NSEntityDescription des NSManagedObjectContext pfiouuu j'ai rapidement abandonné.
Puis j'ai découvert MagicalRecord. Plus besoin de connaà®tre tout ça.
- Je veux récupérer tous les PAC_Pacientes de ma base ? [PAC_Patientes findAll]. C'est tout. Une seule ligne. Même pas besoin d'un MOC, d'une EntityDescription, d'une FetchRequest ou de ce genre de trucs auxquels je ne comprenais rien à l'époque.
- Je veux tous les patients triés par nom ? NSArray* patientes = [PAC_Patientes findAllSortedBy:@nombre]. Pareil, une seule ligne, pas besoin de plein de classes obscures partout
- Je veux récupérer la description du type d'un patient? unPaciente.tipo_de_patiente.descripcion. Basta.
Avec MagicalRecord, tout devient plus simple et magique, bien moins besoin de se prendre la tête ou de commander de l'aspirine quand on veut faire du CoreData. J'ai appris CoreData 10x plus vite. Je sais pas si j'aurais abordé CoreData un jour sans ça tellement ça m'a rebuté avant toutes ces nouvelles classes et lignes à écrire pour un simple fetch.
Bien sûr maintenant que j'ai pratiqué MR et fait pas mal d'applis qui utilisent CoreData, du coup je suis depuis allé plus loin, j'ai découvert les MOC et ce qu'on pouvait faire avec, et plein d'autres trucs, je les utilise maintenant (toujours avec MagicalRecord), mais à mes débuts dans CoreData où j'avais déjà assez de choses à apprendre, j'étais bien content de ne pas avoir à m'en soucier grâce au fait que MR permet de ne pas avoir besoin de savoir ce que c'est si on ne veut pas s'en servir. Ne pas avoir besoin d'apprendre et manipuler 10 nouvelles classes juste pour faire un simple fetch, c'est quand même très appréciable surtout quand on débute sur CoreData.
Tout simplement : unPaciente.tipo_de_paciente.descripcion
Logique!!
Mais dans mon code avec unPaciente.tipo_de_paciente.descripcion, Xcode me marque cette erreur: "Property 'descripcion' not found on object of type 'NSManagedObject *'"
Je suis arrivé à acceder à mon type de patient avec une manip un poil + long:
Pour MR, as tu un tuto à me recomender Aligator?
Merci et a+
OMG quelle horreur !!
Tu as conscience du non-sens de ton code-là ?
1) Tu crees un tout nouveau NSDictionary et l'affecte à une variable unPaciente
2) Sauf que juste après, tu réaffectes cette variable unPaciente à autre chose (au resultat de [listePacientes objectAtIndex:i]). Donc la ligne 1 ne sert strictement à rien
3) En plus tu as déclaré unPaciente comme étant un NSDictionary* alors que listePacientes est un tableau de PAC_Pacientes et pas de NSDictionary, donc tu affectes un objet d'un certain type à une variable d'un autre type
4) Pareil quand tu déclares elTipo, tu crées un tout nouveau NSDictionary tout ça pour rien puisque la ligne d'après tu réaffectes cette variable elTipo à tout autre chose.
5) Et là encore, cet autre chose est un truc qui n'a rien à voir avec un NSDictionary, puisque c'est un NSManagedObject (et même plus précisément tu t'attends à ce que ce soit un TPAC_TipoPaciente pour être précis) et pas du tout un NSDictionary, donc là encore tu affectes des poireaux à des tomates.
Tout ce code que tu fais tu as le gros coup de bol que ça te pète pas à la tronche juste parce que tu utilises les méthodes de KVC ("valueForKey:", qui est une méthode un peu universelle sur NSObject pour récupérer des propriétés via leur nom). Si tu ne sais pas ce qu'est le KVC, comme c'est un design pattern de base en Cocoa, je t'invite à te renseigner sur le sujet.
Je ne vois pas ce que tes NSDictionary (tant la déclaration de tes variables avec ce type que la création de dicos pour rien) viennent foutre là .
Alors que, soit l'utilisation directe du KVC (sans aucun besoin de mettre des NSDictionary qui n'ont rien à voir avec la choucroute) aurait suffi, même si je ne la conseille pas car il n'y a alors aucun type checking, une erreur de frappe dans ta chaà®ne et c'est au Runtime que ça crash donc tu t'en rendras compte trop tard et seulement si tu penses à faire passer ton appli par ce bout de code, tu n'as pas d'autocompletion, ça marchera plus si tu renommes tes propriétés... bref loin d'être idéal.
Et encore 100x mieux que le KVC, l'appel à la propriété directement aurait suffit, à condition de caster ton unPaciente du type générique NSManagedObject en type spécifique PAC_Patiente (ça m'étonne un peu que ce soit pas déjà le cas dans ton tableau, mais bon).
autant pour moi!!