Utilisation de données de base contrôle de version et schémas de migration de schéma

Après avoir lu Premiers pas avec Core Data, nous nous sommes éclairés sur le fonctionnement de Core Data et sur la manière dont il peut nous aider à développer des applications riches en données. Cependant, la surface n’était que rayée et, dans certaines applications, vous pourriez vous demander comment implémenter certaines fonctionnalités..

Mon expérience avec les données de base

Au cours des derniers mois, j'ai travaillé avec Core Data sur un projet animalier. C'est une application qui permet d'extraire des données d'une API de service distante, de les stocker dans Core Data et de les afficher dans une collection de UITableViews. Au cours du développement, il est passé d'un magasin de données basé sur la liste de propriétés (* shudder *) à un magasin Core Data SQL. Après trois reconstructions complètes et de nombreuses nuits de débogage, mon application est enfin devenue un projet rapide, sans crash et sans fuite de mémoire. Pour moi, l'utilisation de Core Data a rendu mon application conforme à son intention et je partagerai avec vous une grande partie de ce que j'ai appris dans cet article et dans les prochains articles..

Pour cet article, nous nous baserons sur la précédente application LapTimer et montrerons comment effectuer des migrations légères..

Changements de schéma, gestion des versions et migrations

Lorsque vous développez une application, vous n'obtiendrez presque jamais le schéma correct du premier coup. Ainsi, Core Data prend en charge la gestion des versions de schéma et la migration des données. Cela vous permet de définir une nouvelle version du schéma Core Data en ajoutant un nouvel attribut ou une nouvelle entité au magasin. Puis définissez comment le magasin doit migrer d'un changement à un autre.

Créer un nouveau xcdatamodel

Core Data traite les versions de schéma différemment de certains autres frameworks que vous utilisiez peut-être dans le passé. Lorsque vous procédez au développement et que vous avez besoin d'un nouvel attribut ou d'une nouvelle entité, vous devez créer un nouveau fichier xcdatamodel pour votre application. Ce nouveau fichier sera versionné, portera un numéro incrémental dans le nom du fichier et se distinguera des versions de schéma antérieures. Dans l'application LapTimer, créez la nouvelle version du modèle de données. Cliquez sur le fichier xcdatamodel dans votre application, puis accédez à l'élément de menu situé à: Conception> Modèle de données> Ajouter une version de modèle.

Vous allez maintenant avoir une arborescence xcdatamodel, le parent étant un nouveau fichier xcdatamodel, avec une nouvelle version du schéma identifiée par le numéro incrémental. En outre, il y a une coche verte contre l'ancien schéma. Cela indique quel schéma est actif et l’application qu’il utilisera. Il est important de noter que le choix immédiat de la nouvelle version peut poser des problèmes de développement. Puisque nous n’avons pas encore configuré de migration pour ce nouveau schéma, si nous devions rendre le nouveau schéma actif, le simulateur ou l’appareil commettrait une erreur et tomberait en panne au démarrage. En guise de démonstration, jetez un coup d'œil à l'erreur ci-dessous, il est courant que les gens rencontrent lors de leur premier essai:

En gros, cela signifie simplement "Hé, vous avez modifié le schéma de la base de données active et je suis bloqué sur une version plus ancienne." Cela évite à l'application des conflits et des erreurs lors de la modification du schéma du magasin de données Core. Il effectue une comparaison basée sur les détails du schéma avec lequel le magasin fonctionne. Si une nouvelle version du schéma lui est attribuée, mais qu'elle ne correspond pas à celle pour laquelle elle a été configurée ou migrée, vous obtenez alors cette erreur.

Alors, comment pouvons-nous surmonter cela? Eh bien, il y a deux options:

  1. Si l'application est en développement et que vous ne vous souciez pas des données de l'application, supprimez simplement l'application du périphérique et réinstallez-la. Il supprimera le magasin et son contenu, mais créera l'application avec le nouveau schéma. Ceci n'est qu'une option en développement.
  2. Utilisez une migration légère pour prendre en charge automatiquement les modifications de schéma mineures à chaque fois que vous les apportez. Ceci est limité à quelques migrations qui sont détaillées ci-dessous.

Migration Légère

C’est une fonctionnalité facile à utiliser et automatique de Core Data, mais elle se limite à de simples migrations, d’où sa légèreté. Vous ne pouvez utiliser cette méthode que si les modifications sont parmi les suivantes:

  • Ajouter un nouvel attribut / propriété à une entité.
  • Renommer une entité ou un attribut / propriété si «l'identifiant de renommage» est donné.
  • Changement d'un attribut / propriété en optionnel ou non optionnel, qu'il nécessite une valeur lors de la création.

Remarque: avant de commencer, si vous travaillez sur le projet LapTimer, vous devez le créer avant de commencer. Assurez-vous que le xcdatamodel actif est la première version avec laquelle l'application a été créée. De cette façon, vous pourrez voir le travail de migration.

À titre de démonstration, l'application LapTimer va modifier l'entité Event en Lap. Avec cela, nous devons également mettre à jour les classes Event.h et Event.m ainsi que toutes les occurrences de celles-ci dans l'application. Avec quelques fonctionnalités astucieuses de Xcode, c'est indolore.

Ainsi, dans la nouvelle version de xcdatamodel que nous avons créée précédemment, je vais effectuer le changement en modifiant simplement les valeurs dans le panneau de détails de l'entité. Nous devons maintenant définir l'identifiant de renommage sur Event. Dans le même panneau, cliquez sur la clé à molette et entrez "Événement" dans le champ Identificateur de renommage, comme suit:

L'étape suivante consiste à indiquer à Core Data qu'il peut effectuer des migrations légères au démarrage. En référençant l'application LapTimer, dans le fichier LapTimerAppDelegate.m, nous devrons ajouter du code à la méthode - (NSPersistentStoreCoordinator *) persistentStoreCoordinator:

 - (NSPersistentStoreCoordinator *) persistentStoreCoordinator if (persistentStoreCoordinator! = Nil) return persistStoreCoordinator;  NSURL * storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @ "LapTimer.sqlite"]]; NSError * error = nil; persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]]; NSDictionary * options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool: YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool: YES], NSInferMappingModelAutomaticallyOption, nil]; if (! [persistentStoreCoordinator addPersistentStoreWithType: NSSQLiteStoreType configuration: nil URL: storeUrl options: options error: & error]) / * Remplace cette implémentation par du code permettant de gérer l'erreur de manière appropriée. abort () force l'application à générer un journal des incidents et à se terminer. Vous ne devez pas utiliser cette fonction dans une application d’expédition, bien que cela puisse être utile lors du développement. S'il n'est pas possible de récupérer l'erreur, affichez un panneau d'alerte qui demande à l'utilisateur de quitter l'application en appuyant sur le bouton Home. Les causes typiques d'erreur sont les suivantes: * Le magasin persistant n'est pas accessible. * Le schéma du magasin persistant est incompatible avec le modèle d'objet géré actuel. Vérifiez le message d'erreur pour déterminer le véritable problème. * / NSLog (@ "Erreur non résolue% @,% @", erreur, [erreur utilisateurInfo]); avorter();  return persistentStoreCoordinator;  

Le code ajouté était les options NSDictionary qui indiqueraient à Core Data d'effectuer des migrations automatiques..

On a presque fini. L'étape suivante consiste à modifier les fichiers de classe de l'entité Event afin de refléter le nouveau nom. Pour ce faire, nous utilisons ma fonctionnalité préférée de Xcode, la fonction Refactor. Comme son nom l'indique, cette fonction va refactoriser et faire une recherche et remplacement plus avancée sur votre projet pour des situations comme celle-ci..

Pour ce faire, vous devez ouvrir Event.m et sélectionner le texte «Event» sur ce fichier. Ensuite, allez dans: Edition> Refactor (Cmd + Shift + J). Up va ouvrir une fenêtre avec des options et des champs comme la capture d'écran ci-dessous. Entrez le mot Lap dans le champ 'Event to'. Cliquez sur preview et vous obtiendrez le résultat de toutes les modifications:

Si vous voulez regarder ce que cela va faire, cliquez sur l'un des fichiers dans le panneau des résultats et cela vous montrera les détails de ce que cela va changer. Il renommera également les fichiers Event.h et Event.m pour nous. Notez que les fichiers xcdatamodel précédents contenant la classe NSManagedObject en cours de remplacement seront légèrement modifiés. Il modifiera le nom de classe de l'entité, et non le nom de l'entité. Ainsi, si un périphérique doit migrer, il peut toujours utiliser la classe d'entités NSManagedObject et les méthodes associées..

Cliquez sur Appliquer. C'est tout. Par mesure de sécurité, il prendra également un instantané, une autre fonctionnalité intéressante de XCode. Donc, si tout se passe mal, vous pouvez simplement revenir à l'instantané précédent, tout comme Time Machine, mais sans toutes les étoiles et l'interface utilisateur galactique de la galaxie..

Malheureusement, cela ne prend pas tous les changements nécessaires. Il reste encore quelques bits de l'application LapTimer qui font référence à Event. Donc, une recherche rapide et remplacement est en ordre. Aller à: Édition> Rechercher dans le projet. Avec la nouvelle fenêtre, entrez Event comme recherche et Lap comme remplacement. Décochez la case "Ignorer la casse", car nous ne voulons que nous intéresser à la stricte capitalisation de la découverte. Puis modifiez le menu déroulant dans lequel «Contains» est sélectionné et sélectionnez «Mots entiers» à la place. Cela réduira la recherche à exactement ce dont nous avons besoin.

Cliquez sur Trouver. Passez en revue les modifications. Si tout s'est bien passé, effectuez le remplacement!

Changer le schéma actif

Nous avons donc créé une nouvelle version du schéma, apporté quelques modifications et il est maintenant temps de placer l'application dans le nouveau schéma..

Rien de compliqué ici. Sélectionnez le nouveau schéma que vous souhaitez définir comme actif et naviguez jusqu'à: Conception> Modèle de données> Définir la version actuelle. La coche verte se déplacera vers le nouveau schéma et tout sera prêt.

Créez et exécutez l'application. Tout devrait aller bien et l'application devrait s'ouvrir, migrer et s'exécuter. Vous ne remarquerez pas du tout cette migration, pas même une sortie du débogueur. Mais le fait que le code soit exécuté et fonctionne prouve qu'il a migré.

résumer

Donc, l'application a maintenant un nom d'entité modifié. Cela peut arriver de temps en temps dans le développement de toute application. Vous pouvez ajouter de nouvelles propriétés avec cette méthode de migration légère avec ce même processus.

Si vous devez modifier le type d'une propriété ou effectuer des modifications plus avancées, vous devrez vous lancer dans la migration d'un objet de modèle de mappage. Il s'agit d'une méthode plus avancée de ce que nous avons effectué, nécessitant des configurations et du code supplémentaires. La documentation Apple iOS décrit parfaitement ce processus de migration avancé..