web-dev-qa-db-fra.com

iPhone Core Data "Migration Légère Automatique"

Je tente de mettre à jour une application qui implémente un magasin de données principal. J'ajoute un attribut à l'une des entités. 

J'ai ajouté le code suivant à ma classe de délégué:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }

    NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"Shoppee.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]) {
        NSLog(@"Error: %@",error);
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }    

    return persistentStoreCoordinator;
}

C'était l'URL suivante: Doc

Je reçois le message d'erreur suivant lors de l'exécution du code:

2009-12-01 20: 04: 22.877

Shoppee [25633: 207] Erreur: Erreur

Domaine = NSCocoaErrorDomain Code = 134130

UserInfo = 0x1624d20 "L'opération n'a pas pu aboutir. (Erreur cacao 134130.)" 2009-12-01 20: 04: 22.879 Shoppee [25633: 207] Erreur non résolue Domaine d'erreur = Code NSCocoaErrorDomain = 134130 UserInfo = 0x1624d20 "L'opération n'a pas pu être achevée. (Erreur cacao 134130.)", { URL = file: //localhost/Users/Eric/Library/Application%20Support/iPhone%20Simulator/User/Applications/A8A8FB73-9AB9-4EB7-8F83-82F5B4467AF1/Documents/MyApp.sqlite.. métadonnées = { NSPersistenceFrameworkVersion = 241; NSStoreModelVersionHashes = { Item = <869d4b20 088e5c44 5c345006 87d245cd 67ab9bc4 14cadf45 180251e9 f741a98f>; Store = <47c250f4 895e6fd1 5033ab42 22d2d493 7819ba75 3c0acffc 2dc54515 8deeed7a>; }; NSStoreModelVersionHashesVersion = 3; NSStoreModelVersionIdentifiers = (); NSStoreType = SQLite; NSStoreUUID = "8DC65301-3BC5-42BE-80B8-E44577B8F8E1"; }; reason = "Impossible de trouver le modèle pour le magasin source"; }

Il semble que j'ai besoin d'inclure le modèle de données d'origine, mais je ne sais pas comment faire. Aucune suggestion?

63
Eric

Pour récapituler/guide complet:

  1. Avant toute modification, créez une nouvelle version du modèle. 

    Dans Xcode 4: Sélectionnez votre .xcdatamodel -> Editeur -> Ajouter la version du modèle. 

    Dans Xcode 3: Design -> Modèle de données -> Ajouter une version de modèle. 

    _ {Vous verrez qu'un nouveau .xcdatamodel est créé dans votre dossier .xcdatamodeld (qui est également créé si vous n'en avez pas)).

  2. Sauvegarder.

  3. Sélectionnez votre nouveau .xcdatamodel et effectuez les modifications que vous souhaitez utiliser conformément à la migration légère documentation .

  4. Sauvegarder.

  5. Définissez le schéma actuel/actif sur le schéma nouvellement créé. 

    Avec le dossier .xcdatamodeld sélectionné:

    Dans Xcode 4: barre latérale Utilitaires -> Inspecteur de fichier -> Modèle de données de base versionné -> Sélectionnez le nouveau schéma. 

    Dans Xcode 3: Design> Modèle de données> Définir la version actuelle. 

    _ {La coche verte sur l'icône .xcdatamodel se déplacera vers le nouveau schéma.

  6. Sauvegarder.

  7. Implémentez le code nécessaire pour effectuer la migration au moment de l'exécution. 

    Lorsque votre NSPersistentStoreCoordinator est créé (généralement la classe AppDelegate), pour le paramètre options, remplacez nil par le code suivant:

    [NSDictionary dictionaryWithObjectsAndKeys:
                      [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 
                      [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil]
    
  8. Exécutez votre application. S'il n'y a pas de plantage, vous avez probablement migré avec succès :)

  9. Une fois la migration réussie, le code de migration (étape 7) peut être supprimé. (Il appartient au développeur de déterminer quand les utilisateurs d'une application publiée peuvent être considérés comme ayant migré.)

IMPORTANT: Ne supprimez pas les anciennes versions/schémas de modèles. Core Data nécessite l'ancienne version pour migrer vers la nouvelle version.

142
Stian Høiland

Je l'ai compris. 

Conception> Modèle de données> Ajouter une version de modèle

26
Eric

Pour les utilisateurs de Google, voici ce que vous devez faire (en supposant que vous ayez déjà configuré Lightweight Migration):

  1. Avant d’apporter des modifications, sélectionnez Conception -> Modèle de données -> Ajouter la version du modèle (vous verrez qu’un nouveau .xcdatamodel est créé dans votre dossier .xcdatamodeld)
  2. Sauvegarder
  3. Faites votre changement
  4. Sauvegarder
  5. Run App

La première étape est cruciale pour que cela fonctionne. J'ai rencontré ce problème parce que j'avais suivi ces étapes pour ajouter un nouveau champ. Ça a marché. J'ai ajouté un deuxième nouveau champ, mais j'ai oublié "Ajouter la version du modèle", et tout a explosé.

15
davetron5000

Aussi pour les googlers .. Règle simple, ne jamais supprimer/éditer une ancienne version numérotée. Lorsque vous ajoutez une version de modèle, le suffixe numérique augmentera de 2..3..4, ce qui signifie que 2 est le plus ancien des 3 suivants, etc.

Ne supprimez pas les anciennes versions de modèle, car les utilisateurs possédant une base de données antérieure utilisant une ancienne version ne pourront pas migrer vers votre dernier modèle de base de données sans comparer les schémas anciens et les derniers.

11
Gmu

Juste une remarque pour ceux qui rencontrent cette recherche sur Google, il semble que même avec la migration automatique (magique), vous devez toujours créer une version de votre magasin d'origine et une nouvelle, et définir la nouvelle comme version actuelle.

5
rustyshelf

Jusqu'ici, je vois seulement comment éviter le message d'erreur.

Mais comment pouvons-nous résoudre le problème - au cas où nous aurions déjà tout gâché? 

La solution suivante corrige le problème mais vous perdrez les données dans la base de données:

Supprimer/renommer le fichier sqlite de l'application déployée/installée.
Les fichiers nommant un emplacement sont donnés directement après le message d'erreur. par exemple.:

reason = Impossible de trouver le modèle pour le magasin source}, {
URL= "file: //localhost/Users/yourName/Library/Application%20Support/iPhone%20Simulator/4.3/Applications/62F342D4-F007-4F6F-96D2-68F902D3719A/Documents/Loc.sqlite;

1
Thorsten Niehues

Quelque chose à garder à l'esprit lors d'une migration légère -

Si vous envisagez de renommer/modifier des attributs, n'oubliez pas de définir la valeur "ID de renommage" dans le nouveau ou l'ancien modèle. Pour utiliser le propre exemple d'Apple, dans XCode 4.3, sélectionnez paintColor dans le nouveau modèle> basculez vers l'inspecteur de modèles de données> définissez le champ "ID de renommage" sur Couleur dans la section "Gestion des versions". Pour moi, le non-respect de cette étape a entraîné une erreur d'exécution. Cette même erreur est aussi couverte ici . En tant que nouvel utilisateur, je ne suis pas autorisé à publier des images. Voici donc un lien imgur (pas du spam, vraiment).

    (Cocoa error 134140.)" UserInfo=0x622b350 {reason=Can't find or automatically infer mapping model for migration
1
Sai Ramachandran

Vous pouvez également obtenir cette erreur lorsque vous modifiez le modèle de données et que vous l'exécutez sur une application installée disposant d'une version différente du fichier sqlite. Dans ce cas, supprimez simplement l'application installée et relancez-la.

0
John Mead