Exercice sur CoreData
Philippe49
Membre
Pour se familiariser avec CoreData, voici une suite à l'exemple de Hillegass (chapitre 30) sur les Departments et Employees, en y ajoutant le troisième étage de la Company. L'objectif serait de pouvoir faire la gestion complète de cette population y compris les mouvements d'employés, éventuellement de départements complets, d'absorption d'une companie par une autre ...
Le second objectif serait l'option de stocker sous la forme d'une plist, ou d'un fichier formaté à ma façon.
1) Double Relationship
Le model initial est représenté ci-dessous. Pensez-vous nécessaire de faire la Relationship entre l'entity Employee et l'entity Company ?
Le second objectif serait l'option de stocker sous la forme d'une plist, ou d'un fichier formaté à ma façon.
1) Double Relationship
Le model initial est représenté ci-dessous. Pensez-vous nécessaire de faire la Relationship entre l'entity Employee et l'entity Company ?
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Si un employé est forcément dans un département et qu'un département est forcément dans une compagnie, alors, par transitivité, un employé est forcément dans une compagnie, si tu veux connaà®tre tous les employés d'un compagnie il suffit de récupérer tous les employés de tous les départements.
Et risque de doublons non synchronisés en plus (par exemple tu risques de pouvoir indiquer qu'un employé est dans une companie par transitivité (car il est dans un département qui est lui-même dans une companie), et oublier de mettre à jour le lien direct employé/companie... qui en plus de faire doublon et est inutile et risque donc de fausser les choses plus que de les améliorer.
Conclusion, non seulement ce n'est pas forcément une bonne idée, mais en plus c'en est plutôt une mauvaise ;D
Oui c'est un peu pourquoi je me posais la question, je veux utiliser les bindings, et je me demandais si c'est plus difficile à synchroniser en triplette qu'en doublette ..
Bon , les Companies tout d'abord
Interface ci-dessous , réglages comme Hillegass. J'ai mis comme d'hab un NSArrayController avec le ManagedObjectContext bindé/synchronisé au managedObjectContext du document. J'ai bien réglé à Entity et Company le panel Attribute.
Surprise : si on ne définit pas le fichier pour l'entity Company, on a le droit à "Failed to create new object" lorsqu'on cherche à ajouter une compagnie. On peut penser que le type de collection utilisé pour Departments est imprécis, et que donner l'interface permet de le préciser.
Les Departments
On rajoute un NSArrayController Departments dans les fichiers du xib, que l'on configure ainsi :
Bindings
MOC : File's Owner managedObjectContext
content set : Company selection departments
Attributes :
Entity Department ,
Prepares Content coché
On rajoute le fichier Departments.h selon la procédure décrite dans Hille gass (new file > choisir Managed Object Class)
Interface pour l'ajout d'un employé
1) Ouverture d'un document fixe au lancement de l'application
C'est pénible de refaire open à chaque fois, et d'avoir un document vide d'ouvert. On définit un delegate de l'application, dans lequel on rédéfinit la méthode applicationShouldOpenUntitledFile: pour répondre NO !
On utilise [NSDocumentController sharedDocumentController] pour ouvrir un document que l'on a déjà enregistré et faire nos tests ainsi.
2) Interface de création d'un nouvel employé
Elle est présentée ci-dessous. Pour les bindings entre les deux menus, on met en place deux Array Controller, un pour chaque pop up.
Indication, parce que ce n'est pas évident , pour maintenir la sélection entre le popup Company et l'array controller associé, on peut utiliser le binding "selectedIndex". Faut le savoir ! >:D
Rq: Je n'ai pas synchronisé les table view et les pop-up ( je m'aperçois que par hasard c'est le cas sur l'image ci-jointe)
Codage de l'ajout d'un employé
On connecte le bouton, et on code
avec quelques broutilles de complément que l'on trouve naturellement
Refactoring du xib
Avant de compléter l'interface, il est temps de clarifier le xib, en introduisant des xib annexes et leurs view controllers. Cette version ne fera que cela, pas de fonctionnalité nouvelle, simplement une réorganisation.
3 xib : MyDocument.xib , Store.xib et AddEmployee.xib
MyDocument.h se décharge d'un certain nombre de tâches sur les deux contrôleurs :
Dans windowControllerDidLoadNib: , le document crée par le code les deux contrôleurs et ajoute leurs vues respectivement dans storeView et dans detailView.
Les classes SpecialViewController et AddEmployeeViewController
Mise en place d'un attribute transformable : une NSColor
1) Transformer la zone DetailView en une detailTabView
On recode la méthode windowControllerDidLoadNib: en installant la vue contrôlée par un addEmployeeViewController dans le premier onglet et celle d'une DepartmentColorViewController dans le second onglet. Par souci d'uniformisation on définit une classe StoreViewController héritant de SpecialViewController qui pourtant l'instant ne définit rien.
Dans le DepartmentColor.xib on aura besoin des mêmes array controller que dans le addEmployee.xib, on peut faire un dupliquer dans le système de fichier, suivi d'un add dans les resources du projet.
2) La couleur dans le model
Ajouter un attribut textColor dans l'entity Department, en choisissant transformable ou Binary Data dans le menu déroulant. Changer le .h et le .m en conséquence.
3) Les bindings pour la couleur
Synchroniser la value du color Well.
On peut essayer ici, on a bien la synchronisation du color well et du popup department. On a perdu momentanément l'ouverture du fichier de test car il n'est plus lisible après le changement du model, cela reviendra au prochain enregistrement.
4) Les bindings pour la couleur dans la table view
Synchroniser le textColor dans la table column , et cocher rich text dans le text field cell de cette dernière.
Coder un NSValueTransformer pour que ce soit une NSAttributedString qui soit présenté par la table view, et non une simple NSString. On en profite pour choisir une police lisible avec la couleur.
Ajouter ce ValueTransformer dans le binding value de la table column.
5) Le titre de la NSBox
L'occasion d'utiliser un Display Pattern : Il faut en utiliser 2 et la syntaxe %{title1}
On remarquera la possibilité de se déplacer entre les table view et à l'intérieur des table view à l'aide de la tbulation et des touches fléchées.
marche pasÂ
[EDIT] Sur un essai simple le backgroundColor d'une table view se binde correctement ...
Bon je laisse tomber, si l'un d'entre vous a une idée ...
Un autre attribut persistent d'un type non standard
Pour confirmer le principe, créer un attribut logo pour les companies, et le récupérer par drag and drop dans une image view. (c'est tout simple, ...)
Que du clic (surtout dans IB) sauf 2 lignes de code :
J'ai essayé d'appliquer un maximum d'attributs juste en bindant dans IB.
Le résultat est un peu laid, mais ça marche (en utilisant ton code pour le binding, enfin il me semble).
Bon, on va aller se boire un coupe de "vieille vigne" pour se refaire la santé.
le Model Key Path @backgroundColor doit être exposé par Apple en "underGround" pour que cela fonctionne, non? ou aurais-je trop bu? :(renaud):
Ce sont les moments les plus productifs ...
En fait, je n'ai pas encore rencontré un exemple où le manque d'un exposeBinding: empêchait le binding de fonctionner...
Ah oui, j'ai fait une erreur classique de le mettre dans initWithNibName:
Merci du coup de pouce
Ben voyons
Implémenter exposeBinding: est nécessaire pour que le binding apparaisse sous IB quand on fait ses propres IBPlugIns, mais on peut tout à fait binder manuellement.
Philippe, as-tu essayé plus simplement:
Je ne vois pas bien quel NSData tu aurais à désarchiver ici (mais il y a peut-être un aspect qui m'échappe).
Ok
Il reste curieux que la doc demande d'exposer les bindings dans les autres cas. Peut-être pour préserver une évolution future ? pour l'analyse en vue des warnings ...
C'est ce que j'ai fait. Je l'avais simplement mal positionné dans le code. (Il faut désarchiver le data pour obtenir la NSColor)
Challenge : Introduire une information sur l'un des attributs
Il s'agit de mettre sur l'onglet logo la taille de l'image/logo attribuée à une entreprise.
Bon on peut rajouter encore un attribut, mais c'est plutôt lourd. Comment faire sans changer quoi que ce soit au ManagedObject Company ?
Valider un changement d'attribut
Lors de l'attribution d'un logo à une compagnie, on prévoit de refuser si la taille du logo est trop importante. Pour cela, on code dans Company.h la méthode :
-(BOOL) validateLogo:(id *)ioValue error:(NSError **)outError ;
et on coche l'option Validates Immediatly dans IB.
Si cette option n'est pas cochée, la validation n'aura lieu que lors de l'enregistrement.
La doc
Dans Company.h :
Dans Company.m :
Ce qui donne :
Utiliser des setter/getter personnalisés , FetchRequest
Lorsque l'on rentre le nom d'un nouvel employé, une sheet indique si existe déjà dans le store un/plusieurs employés dont le nom débute avec le même préfixe, en en faisant la liste.
1) Vérification du bon fonctionnement des setter/getter
On met en place les accesseurs à l'attribut dans l'entité Employee.
La la doc doc[/url] indique précisément comment faire ses setter/getter
personnalisés. Il faut déclarer les méthodes primitives dans le .h et les méthodes setName: et name dans le .m
Vérifier avec un NSLog, ou déjà un NSRunAlertpanel.
2) Dans le setter
La solution donnée utilise une requête sur le modèle de la doc
Cette requête est mise ici dans le setter.
Core Data avec un IKImageBrowserView
1) Les difficultés
Ce n'est pas facile, c'est même acrobatique.
2) La réalisation
Synchroniser le Zoom et la taille de la fonte avec les properties du TakeoverController=File's Owner
(1) J'ai cherché en vain à conserver les versions précédentes en faisant un pont entre logo et imageRepresentation. Pas réussi, il faut dire que j'ai trouvé le truc du imageVersion en dernière minute ... à voir
(2) Le code de cet ArrayController