Que dois-je faire pour que les données de base puissent migrer automatiquement les modèles?
J'ai lu dans la documentation sur la migration automatique /légère pour les modèles de données de base-mais j'ai des problèmes dans la réalité de son implémentation.
Si je comprends bien, l'application devrait remarquer que le modèle qu'elle a et le modèle qui existe déjà sur un périphérique ne sont pas les mêmes. Si vous avez seulement ajouté des attributs ou des relations et des modifications simples similaires, le modèle doit être mis à niveau automatiquement.
Tous les pointeurs - dois-je définir quelque chose xCode?
10 réponses
J'ai maintenant trouvé que c'est assez simple une fois que vous savez où chercher.
Dans mon AppDelegate, j'ai configuré le NSPersistentStoreCoordinator-et vous devez ajouter quelques options à cela pour lui dire de gérer la migration automatique:
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSError *error;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
// Handle error
NSLog(@"Problem with PersistentStoreCoordinator: %@",error);
}
Ensuite, vous devez faire un petit tour dans xCode:
- Sélectionnez votre fichier xcdatamodel
- Sélectionnez le menu conception en haut - puis modèle de données - puis choisissez Ajouter une Version de Modèle
- votre fichier xcdatamodel sera alors déplacé dans un nouveau répertoire avec le même nom que votre fichier xcdatamodel mais avec l'extension xcdatamodeld - il y aura un deuxième fichier dans ce répertoire avec un 2 dans le nom. Sélectionnez le nouveau fichier, puis Design- > modèle de données- > définir la Version actuelle ( dans Xcode 4, vous faites ceci )
- Si vous avez déjà effectué les modifications qui ont rendu votre projet incompatible, retirez ces modifications du fichier XCDATAMODEL d'origine. Si vous n'avez pas encore apporté les modifications , modifiez simplement le 2.fichier xcdatamodel (celui que vous venez de faire la version actuelle).
- Maintenant, lorsque vous installez cette version sur un périphérique qui a l'ancien modèle, il mettra automatiquement à niveau Ce modèle vers le nouveau modèle.
Cela semble génial et aussi simple que je le voulais - mais je pense que vous devez être prudent pendant le développement lorsque vous modifiez un modèle - sinon vous devrez créer une nouvelle version pour chaque changement.
Je pense que ce que je vais faire est que je vais garder tous les fichiers modifiés et puis une fois que je me prépare à déployer ma mise à jour je vais supprimer tous les fichiers intermédiaires et simplement déployer avec les modèles les plus anciens et les plus récents.
Mise à jour (15/07/2011):
Merci à @ rockstarberlin pour avoir signalé qu'il existe une documentation Mise à jour chez apple:
Xcode 4: définition de la Version actuelle d'un modèle D'objet géré
Mise à jour: 8/19/2013 mieux lien:
C'était incroyablement utile. La documentation Apple était-comme d'habitude-terriblement incomplète. Je recommande de faire une construction propre, car j'ai rencontré une erreur "Impossible de fusionner des modèles avec deux entités différentes xxx" lorsque j'ai couru pour la première fois après avoir apporté ces modifications. La nouvelle version fixée.
La réponse de Grouchal est parfaite...mais si vous avez toujours le "Can't merge models with two different entities xxx" même après avoir nettoyé la construction plusieurs fois...Votre peut avoir des problèmes avec la façon dont le managedObjectModel est en cours de chargement...tenir à l'oeil à celui-ci...ce qui m'a aidé à le résoudre..
En outre, si vous êtes tombé sur ce post, comme je l'ai fait, après avoir obtenu l'erreur "le modèle utilisé pour ouvrir le magasin est incompatible avec celui utilisé pour créer le magasin" et vous ne faites que déboguer en utilisant le simulateur et vouloir remplacer complètement l'ancien modèle installé, vous pouvez simplement réinitialiser L'application du simulateur ou supprimer votre application du simulateur fonctionnerait probablement aussi.
Il ne m'est pas venu à l'esprit d'essayer cela avant de lire les messages ici, à quel point j'ai réalisé que j'avais installé l'application dans le simulateur, puis ensuite changé le modèle, provoquant l'erreur d'exécution susmentionnée.
Pour suivre la réponse de Santthosh, j'ai pensé que je publierais l'extrait de code ici à la place. Vous devez créer votre managedObjectModel avec initWithContentsOfURL:
au lieu de mergedModelFromBundles:
sinon vous obtiendrez une erreur:
Impossible de fusionner des modèles avec deux entités XXX et XXX
Si votre fichier de modèle est nommé "Model", voici comment vous créez le managedObjectModel:
NSString *path = [[NSBundle mainBundle] pathForResource:@"Model" ofType:@"momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];
Crédit à ce blog.
Le menu de Xcode 4 a un peu changé. voici une description comment le faire dans Xcode 4:
Xcode 4: définition de la Version actuelle d'un modèle D'objet géré
J'ai eu ce problème pendant des années, et j'ai essayé toutes ces réponses en vain. Aujourd'hui, j'ai finalement compris ce que je faisais mal. Problème très simple, mais je l'ai négligé. Lors de la création d'une version plus récente du modèle de données, si vous ajoutez des colonnes, assurez-vous de les marquer comme facultatives. Si vous ne le faites pas, la migration simple ne fonctionnera pas car les nouvelles valeurs de colonne ne seront pas remplies.
Dès que je me suis assuré que mes nouvelles colonnes ont été" optionnelles", j'ai essayé à nouveau la migration et cela a fonctionné.
Je suis tombé sur ce post à cause d'un problème différent, mais l'erreur était " la configuration du modèle utilisée pour ouvrir le magasin est incompatible avec celle qui a été utilisée pour créer le magasin."
Voici mon problème et la solution. Dans mon modèle, j'ai été en utilisant configurations. Certaines des entités étaient stockées dans un fichier et les autres dans un second fichier. (J'ai quelques valeurs par défaut qui pourraient périodiquement avoir besoin d'être téléchargées, et ce serait un la douleur incroyable pour les fusionner dans l'ensemble). De toute façon, j'ai fait une nouvelle entité. Le programme semblait fonctionner correctement, mais chaque fois que je quittais, j'ai eu l'erreur ci-dessus.
La solution était de regarder mes configurations, de réaliser que j'avais une entité qui n'était actuellement dans aucune des configurations, et de l'ajouter à une. Fonctionne comme un rêve.
Cela ne résoudra pas le problème de L'OP. Mais peut-être qu'une personne frustrée qui atterrit ici via google sera dans le bateau dans lequel j'étais:)
IOS 4.0 +
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"model" withExtension:@"momd"];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
Modification mineure aux instructions géniales de @ Grouchal ci-dessus pour Xcode version 5:
Ancien: 2. Sélectionnez le menu conception en haut - puis modèle de données - puis choisissez Ajouter une Version de modèle
Version 5+: 2. Sélectionnez le menu éditeur, puis ajoutez la version du modèle..., tapez votre nom de Version et en fonction du modèle (sélectionnez votre modèle d'origine dans la liste)