Plus l'iPhone 3 de développement va avoir une brève discussion sur les migrations. Nous allons utiliser les migrations automatiques entre les chapitres où nous ajouter ou de changer le modèle de données. Nous n'allons pas faire discuter les migrations manuel plus complexes, comme Apple couvre ce sujet assez bien dans Versionnage de base du modèle de données et le Guide de migration des données de programmation.
Travail sur le livre, j'ai découvert qu'il ya une vraie chasse aux sorcières dans l'utilisation de migrations avec Core Data sur l'iPhone. Autant que je peux dire, la façon dont vous avez besoin de changer votre projet pour les migrations ne sont pas documentées partout. C'est peut-être là quelque part, mais ce n'est certainement pas sauter aux yeux.
Après avoir créé la première nouvelle version de votre modèle de données, la première chose que vous avez à faire (si vous utilisez les migrations automatiques) est de permettre les migrations automatiques dans votre coordonnateur de stockage persistant. Cette étape est réellement documenté, et il implique simplement de créer une NSDictionary et il passe lorsque vous créez votre coordinateur de stockage persistant. Les modifications apportées à la méthode d'accès qui a été créé automatiquement pour vous dans votre délégué application sont en gras ci-dessous:
De la lecture de la documentation, on dirait que tout ce que vous avez à faire. Puisque vous avez terminé, vous consciencieusement le feu de votre application et obtenir ...
Voici ce qui se passe. L' .xcdatamodel classes ne sont pas copiées dans votre application bundle tel quel. Au lieu de cela, chacun reçoit compilés dans un nouveau fichier de type .mom (Modèle objet géré). Lorsque vous ajoutez une nouvelle version de votre projet, la version actuelle se compile en un .mom fichier en bundle de votre application dans le Resources dossier. Il ne s'arrête pas là, la pensée. Il crée également un dossier (techniquement, un paquet) dans Resources nommé d'après votre modèle de données, mais avec une .momd extension. A l'intérieur du .momd bundle, il met une compilation .mom fichier pour chacun des autres versions de votre modèle de données. Cela est compréhensible. Il a besoin de cette information pour faire la migration automatique.
Voici le problème, cependant. La méthode d'accès par défaut qui est créé managedObjectModel sur votre délégué application crée un modèle objet géré en utilisant une méthode appelée l'usine mergedModelFromBundles:. Cette méthode parcourt tous les fichiers dans le faisceau de votre application à la recherche de tous les .mom. Elle parcourt la structure de répertoire, même en descendant dans les dossiers et les faisceaux. Voici ce que la méthode ressemble comme créé pour vous:
Le hmethod managedObjectModel est complètement inconscient du fait qu'un .momd dossier contient les anciennes versions du même modèle de données, et donc il tente de fusionner chaque version de votre modèle de données en un seul modèle fusionné. Depuis des versions différentes du même modèle de données ont généralement les mêmes entités, la fusion échoue et vous obtenez un message d'erreur similaire à celui ci-dessus parce que les entités doivent être uniques. Vous ne pouvez pas avoir trop de "foo" entités dans un modèle de données unique.
Voici l'étape qui semble avoir été oublié dans la documentation1. Si vous souhaitez utiliser les migrations, vous devez créer manuellement votre modèle de données de la .momd faisceaux. Ouais, peut créer un modèle de données en fournissant un chemin d'accès au .momd bundle au lieu d'un .mom fichier, et c'est ce que vous devriez faire si vous allez utiliser des versions. Voici ce que la nouvelle version pourrait ressembler si vous avez un modèle de données unique:
NSManagedObjectModel requiert une URL de spécifier manuellement l'emplacement d'un fichier, donc nous avons d'abord obtenir le chemin d'NSBundle, puis l'utiliser pour créer un fichier, puis l'utiliser pour charger le fichier modèle de données.
Avec cette nouvelle version en place, les migrations automatiques devraient fonctionner, et vous devriez être mis en place pour faire des migrations manuel basé sur les instructions de la documentation d'Apple.
1 - En défense d'Apple, la documentation ne vous dites can ce faire, il n'a tout simplement pas qu'il soit clair que vous avez besoin.
Travail sur le livre, j'ai découvert qu'il ya une vraie chasse aux sorcières dans l'utilisation de migrations avec Core Data sur l'iPhone. Autant que je peux dire, la façon dont vous avez besoin de changer votre projet pour les migrations ne sont pas documentées partout. C'est peut-être là quelque part, mais ce n'est certainement pas sauter aux yeux.
Après avoir créé la première nouvelle version de votre modèle de données, la première chose que vous avez à faire (si vous utilisez les migrations automatiques) est de permettre les migrations automatiques dans votre coordonnateur de stockage persistant. Cette étape est réellement documenté, et il implique simplement de créer une NSDictionary et il passe lorsque vous créez votre coordinateur de stockage persistant. Les modifications apportées à la méthode d'accès qui a été créé automatiquement pour vous dans votre délégué application sont en gras ci-dessous:
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"Foo.sqlite"]];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return persistentStoreCoordinator;
}De la lecture de la documentation, on dirait que tout ce que vous avez à faire. Puisque vous avez terminé, vous consciencieusement le feu de votre application et obtenir ...
Impossible de fusionner des modèles avec deux entités différentes nommé «Foo»Eh bien, Frack.
Voici ce qui se passe. L' .xcdatamodel classes ne sont pas copiées dans votre application bundle tel quel. Au lieu de cela, chacun reçoit compilés dans un nouveau fichier de type .mom (Modèle objet géré). Lorsque vous ajoutez une nouvelle version de votre projet, la version actuelle se compile en un .mom fichier en bundle de votre application dans le Resources dossier. Il ne s'arrête pas là, la pensée. Il crée également un dossier (techniquement, un paquet) dans Resources nommé d'après votre modèle de données, mais avec une .momd extension. A l'intérieur du .momd bundle, il met une compilation .mom fichier pour chacun des autres versions de votre modèle de données. Cela est compréhensible. Il a besoin de cette information pour faire la migration automatique.
Voici le problème, cependant. La méthode d'accès par défaut qui est créé managedObjectModel sur votre délégué application crée un modèle objet géré en utilisant une méthode appelée l'usine mergedModelFromBundles:. Cette méthode parcourt tous les fichiers dans le faisceau de votre application à la recherche de tous les .mom. Elle parcourt la structure de répertoire, même en descendant dans les dossiers et les faisceaux. Voici ce que la méthode ressemble comme créé pour vous:
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
return managedObjectModel;
}Le hmethod managedObjectModel est complètement inconscient du fait qu'un .momd dossier contient les anciennes versions du même modèle de données, et donc il tente de fusionner chaque version de votre modèle de données en un seul modèle fusionné. Depuis des versions différentes du même modèle de données ont généralement les mêmes entités, la fusion échoue et vous obtenez un message d'erreur similaire à celui ci-dessus parce que les entités doivent être uniques. Vous ne pouvez pas avoir trop de "foo" entités dans un modèle de données unique.
Voici l'étape qui semble avoir été oublié dans la documentation1. Si vous souhaitez utiliser les migrations, vous devez créer manuellement votre modèle de données de la .momd faisceaux. Ouais, peut créer un modèle de données en fournissant un chemin d'accès au .momd bundle au lieu d'un .mom fichier, et c'est ce que vous devriez faire si vous allez utiliser des versions. Voici ce que la nouvelle version pourrait ressembler si vous avez un modèle de données unique:
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
NSString *path = [[NSBundle mainBundle] pathForResource:@"Foo" ofType:@"momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];
return managedObjectModel;
}NSManagedObjectModel requiert une URL de spécifier manuellement l'emplacement d'un fichier, donc nous avons d'abord obtenir le chemin d'NSBundle, puis l'utiliser pour créer un fichier, puis l'utiliser pour charger le fichier modèle de données.
Avec cette nouvelle version en place, les migrations automatiques devraient fonctionner, et vous devriez être mis en place pour faire des migrations manuel basé sur les instructions de la documentation d'Apple.
1 - En défense d'Apple, la documentation ne vous dites can ce faire, il n'a tout simplement pas qu'il soit clair que vous avez besoin.
Aucun commentaire:
Enregistrer un commentaire