Coredata: autoincrémenter une valeur
Tournesol
Membre
Bonjour à tous,
Je tente d'apprendre à utiliser coredata, mais j'ai déjà un petit problème. J'ai une entité "client", qui a divers attributs, tels que nom, prénom, adresse, etc. mais également un attribut ID que j'aimerais incrémenter à chaque ajout d'un nouveau client. Et je ne sais pas exactement comment m'y prendre, j'aurais deux pistes:
1. faire un fetch pour avoir tous les attributs ID de mon entité client dans un tableau, et ensuite trouver la valeur maximale du tableau;
2. utiliser les bindings: un utilisant interface builder j'arrive à obtenir dans un champ texte la valeur maximale de mes ID, en configurant les bindings comme cela:
value:
Bind to: Clients (qui est un NSArrayController lié à mon entité "client")
Controller Key: arrangedObjects
Model Key Path: @max.ID
Maintenant ma question serait: comment faire la même chose dans XCode, car je n'ai pas envie que cette valeur soit affichée dans un champ de texte, mais j'ai envie de l'utiliser dans mon code.
Voilà , j'espère que j'ai réussi à me faire comprendre... Désolé pour ce long message. ça serait vraiment sympa si quelqu'un pouvait me donner son avis, ou une piste... Merci d'avance!
Je tente d'apprendre à utiliser coredata, mais j'ai déjà un petit problème. J'ai une entité "client", qui a divers attributs, tels que nom, prénom, adresse, etc. mais également un attribut ID que j'aimerais incrémenter à chaque ajout d'un nouveau client. Et je ne sais pas exactement comment m'y prendre, j'aurais deux pistes:
1. faire un fetch pour avoir tous les attributs ID de mon entité client dans un tableau, et ensuite trouver la valeur maximale du tableau;
2. utiliser les bindings: un utilisant interface builder j'arrive à obtenir dans un champ texte la valeur maximale de mes ID, en configurant les bindings comme cela:
value:
Bind to: Clients (qui est un NSArrayController lié à mon entité "client")
Controller Key: arrangedObjects
Model Key Path: @max.ID
Maintenant ma question serait: comment faire la même chose dans XCode, car je n'ai pas envie que cette valeur soit affichée dans un champ de texte, mais j'ai envie de l'utiliser dans mon code.
Voilà , j'espère que j'ai réussi à me faire comprendre... Désolé pour ce long message. ça serait vraiment sympa si quelqu'un pouvait me donner son avis, ou une piste... Merci d'avance!
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Alors je progresse :-) J'arrive à déterminer la valeur du prochain ID, je procède de la façon suivante:
Mon bouton "Nouveau client" exécute l'action "ajouterClient" dans laquelle j'arrive à déterminer quel sera le prochain ID. Pour l'instant, elle est codée comme cela ("clients" pointe vers mon NSArrayController):
L'action détermine le nouvel ID à attribuer au client créé et elle ajoute une entrée. Par contre, je n'arrive pas à enregistrer la valeur nouvelID...
J'ai essayé de faire qqch comme
ça ne marche pas... quelqu'un aurait-il une idée?
Merci!
Je n'ai pas encore testé, mais ne faudrait-il pas mettre à la ligne 7:
?
Je vais essayer ce code! Merci!
J'ai dû écrire:
Mais de rien !
Ok, et sans le arrangedObjects ça fait quoi ?
En fait non, Apple préconise plutôt de surcharger la méthode "awakeFromInsert" de l'objet, qui est appelée une seule fois à sa création.
http://developer.apple.com/documentation/Cocoa/Conceptual/NSPersistentDocumentTutorial/03_CustomClass/chapter_4_section_4.html
+
Chacha
Sans le arrangedObjects, ça compile, mais à l'exécution ça ne fonctionne pas. Dans la fenêtre Run Log, j'ai ce message d'erreur:
*** NSRunLoop ignoring exception '[<ArrayControllerWithIDAutoIncrement 0x36c070> valueForUndefinedKey:]: this class is not key value coding-compliant for the key @max.' that raised during posting of delayed perform with target 3aaed0 and selector 'invokeWithTarget:'
Chacha: merci pour le lien! Je n'ai pas fait ce tutoriel, je crois que je devrais...
Je ne sais pas exactement quel est le problème, mais sous-classer NSArrayControlle rjuste pour ça me semble de toutes façons un peu dommage. Le "awakeFromInsert" est plus intéressant car il est fait pour ça !
C'est un tutoriel intéressant, en effet ! Il demande de connaà®tre les Bindings et le KVO (key-value observing), sur lesquels Apple fournit une documentation aussi. Mais pour les Bindings, tu as l'air de connaà®tre !
+
Chacha
Ne connaissant pas du tout Core Data, j'ai aiguillé Tournesol selon mes connaissances, mais à la vue de la doc et des exemples, il est vrai que la méthode awakeFromInsert est plus appropriée car faisant directement partie de Core Data, mais cela demande toujours un sous-classement (NSManagedObject). Â
Ouaip, et t'as bien fait (mieux vaut une solution qu'aucune) ! Mais comme j'ai lu la doc de CoreData y a pas longtemps, cet exemple m'était revenu. Faudrait que je pratique, par contre, parce que ça a l'air très très bien, mais forcément un peu difficile.
+
Chacha
Oui, je pense qu'il est indispensable de bien maitriser les bindings avant de s'attaquer à Core Data, car cela rajoute encore une couche supplémentaire, et l'on peu vite se perdre dès que l'on a besoin de faire quelque chose d'un peu spécial. Ceci dit, je suis tout à fait d'accord avec le fait que cela doit avoir ses avantages quand l'on maitrise.
Effectivement, je pense que je vais plutôt utiliser cette solution, mais j'ai tout de même un problème. Pour incrémenter ma valeur, je dois déterminer la valeur maximale parmi tous les "id" du NSArrayController. Comment accéder au NSArrayController qui contient tous les clients? En sous-classant NSArrayController, j'y accédais simplement avec "self", mais là je ne vois pas trop comment m'y prendre... Il y a peut-être une possibilité d'utiliser la méthode -managedObjectContext de managedObject. Je vais faire quelques tests! Sinon je pourrais utiliser une fetched property.
et ça fonctionne!
mais je me demande si c'est très fiable, et si ça fonctionne si j'ai une autre entité qui a aussi un attribut "id"...
J'ai essayé de faire une fetched property (nom: maxID) qui a comme expression: id == @max.id pour sélectionner l'objet avec le plus grand id. Ensuite dans awakeFromInsert, pour avoir mon nouvel id, j'écris:
Mais ça ne fonctionne pas, et je comprends pas pourquoi...
Bon, je continue à chercher!
Créer une nouvelle entité par ex ID, dans laquelle on peut mettre tous ses id pour chaque autre entité, après à chaque nouvelle entrée dans ton autre entité il suffit d'incrémenter d'un la propriété de ton entité ID et d'ensuite récupérer cette ID et hop on le récupère dans l'autre entité.
Si quelqu'un est intéressé je dois avoir un bout de code pour faire comme ça
Anthony
Ah j'avais pas pensé à ce type de solution. ça devrait marcher, je préfèrerais éviter de créer encore une nouvelle entité, mais si je ne trouve pas de solution pourquoi pas. Ce qui me gêne tout de même, c'est qu'on dit habituellement qu'il faut éviter d'enregistrer dans une base de donnée une information qui peut être déduite d'autres informations enregistrées. Or ici c'est le cas, car tous les id sont enregistrés, il est donc facile en théorie de trouver le plus grand.
J'espère encore trouver une solution un peu plus élégante, mais merci pour la proposition.
C'est vrai que ça aurait été mieux de mettre l'autoincrémentation dans la méthode awakeFromInsert, mais c'est un peu compliqué. J'ai trouvé une solution, en écrivant dans ma sous-classe de NSManagedObject les deux méthodes suivantes:
Mais il y a un petit bug: les clients que j'ajoute apparaissent à double dans ma table qui contient et affiche tous les clients. Pourtant l'enregistrement se fait correctement, et quitter puis relancer le programme suffit à corriger l'affichage. Mais je ne sais pas comment corriger ça, et finalement je trouve que la solution de sous-classer NSArrayController est plutôt bien!
Alors merci à tous pour votre aide et vos conseils/suggestions!