Données de base – Migration par défaut (manuel)

J'ai lu tous les blogs possibles et SO postr sur le sujet – mais toujours pas sûr de ce qui se passe. J'ai aussi lu ceci mais toujours pas de chance – leur guide sur la migration par défaut est clair mais ne fonctionne pas dans ma situation. Je suis relativement nouveau dans le développement iOS, alors soyez gentil 🙂

Voici la situation: sur l'entité appelée Rapport dans mon application (iOS), les changements suivants doivent avoir lieu:

atsortingbut de données – supprimé

atsortingbut de titre – ajouté

L' atsortingbut reportId doit être changé de Integer 16 en Ssortingng. C'est ce qui cause mes problèmes. J'ai créé une nouvelle version du model de données de mon model actuel et j'ai modifié les attributes.

D'abord voici quelques methods de l'application:

- (NSManagedObjectModel *)managedObjectModel { if (__managedObjectModel != nil) { return __managedObjectModel; } NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"App" withExtension:@"momd"]; __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; return __managedObjectModel; } 

et alors

 /** Returns the persistent store coordinator for the application. If the coordinator doesn't already exist, it is created and the application's store added to it. */ - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { if (__persistentStoreCoordinator != nil) { return __persistentStoreCoordinator; } NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"App.sqlite"]; NSError *error = nil; __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; NSLog(@"Which Current Version is our .xcdatamodeld file set to? %@", [[self managedObjectModel] versionIdentifiers]); NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, //Commented for manual migration [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil]; if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } return __persistentStoreCoordinator } 

J'ai d'abord essayé la migration légère. Il a échoué avec

 reason=Can't find mapping model for migration 

Puis j'ai fait ce qui suit juste pour essayer: rendre l'atsortingbut reportId à ce qu'il était (Interger 16, en gardant les deux autres changements dans le model.) La migration Lightweight a bien fonctionné.

Ok, j'ai pensé, il doit probablement avoir un mappage manuel afin de gérer le changement de type de données. Donc, j'ai créé le model de mappage (dans lequel j'ai essayé de définir reportId à la fois "", et source.reportId), désactivé la migration légère. Depuis que je suis nouveau à cela, j'ai décidé de prendre des mesures de bébé et ne pas faire ce reportId Int> Chaîne pour le moment et tester ma cartographie. Et ça n'a pas marché. Avec la même raison = Impossible de find le model de mappage pour la migration. J'ai essayé de changer reportId en Ssortingng comme il se doit – même résultat. Il me semble presque que mon model de cartographie est complètement ignoré. En fait, j'ai essayé de le supprimer – même résultat même erreur. Qu'est-ce que je manque ici?

  ## EDIT ## 

Ok, je dois aller au fond des choses, j'ai téléchargé l'application que Mihai avait mise en place (merci!) Et j'ai commencé à jouer avec. J'ai modifié le coordinateur de magasin persistant pour qu'il corresponde à ce que j'ai pour "Migration par défaut"

 - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { if (__persistentStoreCoordinator != nil) { return __persistentStoreCoordinator; } NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"TestData.sqlite"]; NSError *error = nil; __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, nil]; if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } return __persistentStoreCoordinator; } 

Et j'ai l'erreur qui a tout à fait du sens pour moi. Il a fondamentalement trouvé le bon model de mappage et a essayé de le faire correspondre et a donné une erreur très valide. 2012-02-07 10: 47: 39.246 TestData [2008: 707] *** App terminant en raison d'une exception non interceptée 'NSInvalidArgumentException', raison: 'Type de valeur inacceptable pour l'atsortingbut: property = "reportId"; type désiré = NSSsortingng; type donné = __NSCFNumber; valeur = 1. '

Où dans mon cas j'ai une décharge qui ressemble à ceci (juste une petite partie du journal):

  Report = "(<NSEntityDescription: 0x1708d0>) name Report, managedObjectClassName Report, renamingIdentifier Report, isAbstract 0, superentity name (null), properties {\n action = \"(<NSAtsortingbuteDescription: 0x170a30>), name action, isOptional 1, isTransient 0, entity Report, renamingIdentifier action, validation predicates (\\n), warnings (\\n), versionHashModifier (null)\\n userInfo {\\n}, atsortingbuteType 100 , atsortingbuteValueClassName NSNumber, defaultValue 0\";\n data = \"(<NSAtsortingbuteDescription: 0x1709e0>), name data, isOptional 1, isTransient 0, entity Report, renamingIdentifier data, validation predicates (\\n), warnings (\\n), versionHashModifier (null)\\n userInfo {\\n}, atsortingbuteType 700 , atsortingbuteValueClassName NSSsortingng, defaultValue (null)\";\n reportId = \"(<NSAtsortingbuteDescription: 0x170a80>), name reportId, isOptional 1, isTransient 0, entity Report, renamingIdentifier reportId, validation predicates (\\n), warnings (\\n), versionHashModifier (null)\\n userInfo {\\n}, atsortingbuteType 100 , atsortingbuteValueClassName NSNumber, defaultValue 0\";\n timestamp = \"(<NSAtsortingbuteDescription: 0x170ad0>), name timestamp, isOptional 1, isTransient 0, entity Report, renamingIdentifier timestamp, validation predicates (\\n), warnings (\\n), versionHashModifier (null)\\n userInfo {\\n}, atsortingbuteType 900 , atsortingbuteValueClassName NSDate, defaultValue (null)\";\n type = \"(<NSAtsortingbuteDescription: 0x170990>), name type, isOptional 1, isTransient 0, entity Report, renamingIdentifier type, validation predicates (\\n), warnings (\\n), versionHashModifier (null)\\n userInfo {\\n}, atsortingbuteType 100 , atsortingbuteValueClassName NSNumber, defaultValue 0\";\n}, subentities {\n}, userInfo {\n}, versionHashModifier (null)"; }, fetch request templates { }, reason=Can't find mapping model for migration}, { 

EDIT 2

Au point où j'ai 'NSInvalidArgumentException', raison: 'Mismatch entre le mapping et les templates source / destination' – à la fois les templates source et destination et les templates de mapping, tout semble comme il se doit. Je suis sur le point d'abandonner et prêt à perdre datatables dans cette entité de rapport .. Y at-il un moyen de le faire?

EDIT 3

Donc, juste pour essayer les choses, j'ai rollback mon model où il était avant toute cette folie, créé une nouvelle version dans laquelle j'ai fait un seul changement – laissé tomber un champ. Et puis j'ai créé un model de cartographie et j'essaie de l'utiliser. – Même erreur Incompatibilité entre les templates de mappage et de source / destination – il semble que le model de mappage généré soit mauvais en quelque sorte, mais en le regardant – je n'ai vu aucun problème.

Avec l'aide que j'ai eu de cette question, j'ai pu résoudre votre problème.

J'ai mis en place une application de démonstration basée sur le model maître / détail par défaut avec des données de base. Lorsque vous l'exécutez pour la première fois, assurez-vous que le model "TestData" est sélectionné dans "TestData.xcdatamodeld". Ajoutez des lignes, puis passez à "TestData 2.xcdatamodel" et la migration effectuera les modifications appropriées.

L'application de démonstration peut être téléchargée à partir d' ici

Si vous n'avez pas trouvé de réponse, je peux vous suggérer une petite astuce. Premièrement, idk pourquoi cela arrive mais le model source, le model de destination et le model de mapping ont des valeurs différentes de versionHashes pour les mêmes entités.

J'ai programmaticaly les a corrigées et la migration se produit.

  NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"Model" withExtension:@"cdm"]; NSMappingModel *mappingModel = [[NSMappingModel alloc] initWithContentsOfURL:fileURL]; NSArray *newEntityMappings = [NSArray arrayWithArray:mappingModel.entityMappings]; for (NSEntityMapping *entityMapping in newEntityMappings) { [entityMapping setSourceEntityVersionHash:[sourceModel.entityVersionHashesByName valueForKey:entityMapping.sourceEntityName]]; [entityMapping setDestinationEntityVersionHash:[destinationModel.entityVersionHashesByName valueForKey:entityMapping.destinationEntityName]]; } mappingModel.entityMappings = newEntityMappings; BOOL ok = [migrationManager migrateStoreFromURL:sourceStoreURL type:sourceStoreType options:nil withMappingModel:mappingModel toDestinationURL:destinationStoreURL destinationType:destinationStoreType destinationOptions:nil error:&error];