web-dev-qa-db-fra.com

Le modèle utilisé pour ouvrir le magasin est incompatible avec celui utilisé pour créer le magasin.

J'ai créé un modèle Core Data dans xcode 3.2 et, après la mise à niveau dans Xcode 4.2, j'ai ensuite ajouté une nouvelle entité de la sous-classe NSManagedObject (reportez-vous à la nouvelle entité).

D'abord, ça a l'air bizarre parce que ce n'est pas dans le même groupe que l'ancien. Voici la photo sur mon xcode 4.2 (AlkitabDB est celui créé dans xcode 3.2, EndeDB est le nouveau de la version actuelle de xcode (4.2):

the new entity do not grouped in xdatamodel

Seconde chose, je l’ai laissée telle quelle, puis j’ai accédé à la deuxième entité (la nouvelle) de la même manière que la première entité (l’ancienne) et l’erreur telle qu’appelée apparaît.

Voici l'erreur:

2012-01-16 21:13:38.496 iHuria[55953:207] Unresolved error Error Domain=NSCocoaErrorDomain Code=134100 "The operation couldn’t be completed. (Cocoa error 134100.)" UserInfo=0x8829cd0 {metadata=<CFBasicHash 0x882a370 [0x1839b38]>{type = immutable dict, count = 7,
entries =>
    2 : <CFString 0x8829b90 [0x1839b38]>{contents = "NSStoreModelVersionIdentifiers"} = <CFArray 0x8829ff0 [0x1839b38]>{type = immutable, count = 0, values = ()}
    4 : <CFString 0x8829bc0 [0x1839b38]>{contents = "NSPersistenceFrameworkVersion"} = <CFNumber 0x8829770 [0x1839b38]>{value = +320, type = kCFNumberSInt64Type}
    6 : <CFString 0x8829bf0 [0x1839b38]>{contents = "NSStoreModelVersionHashes"} = <CFBasicHash 0x882a080 [0x1839b38]>{type = immutable dict, count = 1,
entries =>
    0 : <CFString 0x882a010 [0x1839b38]>{contents = "AlkitabDB"} = <CFData 0x882a030 [0x1839b38]>{length = 32, capacity = 32, bytes = 0xd02ac5f8be6ab0b39add450aca202ac0 ... 3d45d462998d2ccd}
}

    7 : <CFString 0x10e3aa8 [0x1839b38]>{contents = "NSStoreUUID"} = <CFString 0x8829e60 [0x1839b38]>{contents = "4F2EE7FF-463B-4055-BBED-8E603CDBDF59"}
    8 : <CFString 0x10e3948 [0x1839b38]>{contents = "NSStoreType"} = <CFString 0x10e3958 [0x1839b38]>{contents = "SQLite"}
    9 : <CFString 0x8829c40 [0x1839b38]>{contents = "NSStoreModelVersionHashesVersion"} = <CFNumber 0x6b1c7c0 [0x1839b38]>{value = +3, type = kCFNumberSInt32Type}
    10 : <CFString 0x8829c70 [0x1839b38]>{contents = "_NSAutoVacuumLevel"} = <CFString 0x882a0c0 [0x1839b38]>{contents = "2"}
}
, reason=The model used to open the store is incompatible with the one used to create the store}, {
    metadata =     {
        NSPersistenceFrameworkVersion = 320;
        NSStoreModelVersionHashes =         {
            AlkitabDB = <d02ac5f8 be6ab0b3 9add450a ca202ac0 ebd1e860 cbb578c2 3d45d462 998d2ccd>;
        };
        NSStoreModelVersionHashesVersion = 3;
        NSStoreModelVersionIdentifiers =         (
        );
        NSStoreType = SQLite;
        NSStoreUUID = "4F2EE7FF-463B-4055-BBED-8E603CDBDF59";
        "_NSAutoVacuumLevel" = 2;
    };
    reason = "The model used to open the store is incompatible with the one used to create the store";
}

J'ai déjà recherché la solution et découvert que je devais supprimer l'application du simulateur et l'exécuter à nouveau, mais cela n'a pas fonctionné. Est-ce que quelqu'un connaît une solution à ce problème? S'il vous plaît aider.

179
dejoong

La suppression de l'application n'est parfois pas le cas! Suggérez, votre application a déjà été publiée! Vous ne pouvez pas simplement ajouter une nouvelle entité à la base de données et continuer - vous devez effectuer une migration!

Pour ceux qui ne veulent pas creuser dans la documentation et qui cherchent une solution rapide:

  1. Ouvrez votre fichier .xcdatamodeld
  2. cliquez sur l'éditeur
  3. sélectionnez Ajouter la version du modèle ...
  4. Ajouter une nouvelle version de votre modèle (le nouveau groupe de modèles de données ajouté)
  5. sélectionnez le fichier principal, ouvrez l'inspecteur de fichiers (panneau de droite)
  6. et sous Versioned core data model sélectionnez votre nouvelle version du modèle de données pour le modèle de données actuel
  7. CE N'EST PAS TOUT) Vous devez effectuer ce que l'on appelle "migration légère".
  8. Allez dans votre AppDelegate et trouvez où est créé le persistentStoreCoordinator
  9. Trouver cette ligne if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error])
  10. Remplacez les options nil par @{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES} (fourni dans le code commenté de cette méthode).
  11. Voilà, amusez-vous!

P.S. Cela s'applique uniquement à la migration légère. Pour que votre migration soit considérée comme une migration légère, vos modifications doivent être limitées à cette bande étroite:

  • Ajouter ou supprimer une propriété (attribut ou relation).
  • Rendre une propriété non optionnelle optionnelle.
  • Définissez un attribut facultatif non optionnel, à condition de fournir une valeur par défaut.
  • Ajouter ou supprimer une entité.
  • Renommez une propriété.
  • Renommez une entité.

Pour Swift 4

coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true])
284
Stas

Supprimez l'application du simulateur et effectuez un nettoyage de votre projet. Cela devrait éclaircir ces questions. Assurez-vous de ne pas exécuter le débogueur lorsque vous supprimez l'application, sinon elle ne sera pas supprimée correctement.

Si vous voulez vous assurer qu'il est parti, consultez le répertoire Users/INSERT_YOUR_USER_HERE/Library/Application Support/iPhone Simulator/ du dossier de votre application, sous la version que vous exécutez.

Note: Ceci est pour le développement seulement. Pour la production, vous devez implémenter une sorte de migration. Google "Migration de données de base", la migration légère étant la plus simple.

283
Philippe Sabourin

Ajoutez simplement l'attribut Options lors de la création de persistentStoreCoordinator dans le fichier AppDelegate.m pour la méthode de données principale, comme indiqué ci-dessous.

OBJECTIF-C

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil)
    {
        return _persistentStoreCoordinator;
    }

    NSLog(@"persistentStoreCoordinator___");
    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"MyApp.sqlite"];

    NSMutableDictionary *options = [[NSMutableDictionary alloc] init];
    [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
    [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];

    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();
    }

    NSLog(@"persistentStoreCoordinator___2");
    return _persistentStoreCoordinator;
}

rapide

    lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
    // The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
    // Create the coordinator and store
    let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
    let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite")
    var failureReason = "There was an error creating or loading the application's saved data."

    // MAIN LINE OF CODE TO ADD
    let mOptions = [NSMigratePersistentStoresAutomaticallyOption: true,
                    NSInferMappingModelAutomaticallyOption: true]

    do {
        try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: mOptions)
    } catch {
        // Report any error we got.
        var dict = [String: AnyObject]()
        dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
        dict[NSLocalizedFailureReasonErrorKey] = failureReason

        dict[NSUnderlyingErrorKey] = error as NSError
        let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
        // Replace this with code to handle the error appropriately.
        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
        abort()
    }

    return coordinator
}

Il avait résolu mon problème ..

33
Dhaval H. Nena

Answer: Supprimez l'application du simulateur, effectuez un nettoyage et reconstruisez votre projet.

Remarque: Lorsque vous apportez des modifications à la définition de Core Data, supprimez l'application installée sur le périphérique physique ou le simulateur, nettoyez le projet et reconstruisez à nouveau.

23
Bhavin

Oui. Une fois que vous supprimez une application sur un périphérique physique et que vous le reconstruisez, cela fonctionne.

14
world-software.net

Pour Swift, dans AppDelegate.Swift, trouvez la ligne

try coordinator!.addPersistentStoreWithType(NSXMLStoreType, configuration:  nil, URL: url, options: nil )

et le remplacer par

try coordinator!.addPersistentStoreWithType(NSXMLStoreType, configuration: nil, URL: url, options: [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true])
14

Je viens de passer plusieurs jours à combattre cette erreur, ainsi que les plantages de mergedModelFromBundles et à obtenir l'erreur "Impossible de fusionner des modèles avec deux entités différentes nommées *".

Il se trouve que le problème fondamental était que Xcode ne supprimait pas les anciennes ressources des périphériques et que j'avais d'anciennes versions de mon modèle de données (fichiers .mom) qui étaient à l'origine de conflits. C'est pourquoi la suppression de l'application a résolu le problème sur l'un de mes appareils.

Après avoir trouvé cet article de blog via une autre SO réponse, j'ai rendu mon application plus tolérante vis-à-vis des anciens modèles en modifiant cette ligne qui recherche TOUS les fichiers .mom:

NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];

à cela, qui ne regarde que dans le répertoire Filters:

NSString *path = [[NSBundle mainBundle] pathForResource:@"Filters" ofType:@"momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];

J'ai utilisé recursivePathsForResourcesOfType de this so question : pour vous aider à comprendre cela en enregistrant tous les fichiers .mom dans l'application:

NSArray *momPaths = [self recursivePathsForResourcesOfType:@"mom" inDirectory:[[NSBundle mainBundle] resourcePath]];
NSLog(@"All .mom files:%@",momPaths);

J'ai aussi utilisé iExplorer pour regarder les fichiers .mom superflus (je n'ai pas encore essayé de les supprimer).

La méthode ci-dessous était également utile. Cela montrait qu’une entité était dans le modèle fusionné renvoyé par [psc managedObjectModel] et n’existait plus dans aucun de mes modèles ou dans le magasin lui-même. C’est ce qui me laissait croire qu’un ancien modèle était mis en cache sur l’appareil lui-même que le bâtiment propre n’avait pas supprimé. La méthode enregistre chaque entité identique, modifiée, ajoutée ou supprimée du modèle. (écrit avec this SO answer comme point de départ):

- (BOOL)comparePersistentStore:(NSPersistentStoreCoordinator *)psc withStoreURL: (NSURL *)storeURL {
    NSError *error = nil;

    // Get the entities & keys from the persistent store coordinator
    NSManagedObjectModel *pscModel = [psc managedObjectModel];
    NSDictionary *pscEntities = [pscModel entitiesByName];
    NSSet *pscKeys = [NSSet setWithArray:[pscEntities allKeys]];
    //NSLog(@"psc model:%@", pscModel);
    //NSLog(@"psc keys:%@", pscKeys);
    NSLog(@"psc contains %d entities", [pscModel.entities count]);

    // Get the entity hashes from the storeURL
    NSDictionary *storeMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType
                                                                                          URL:storeURL
                                                                                        error:&error];
    NSDictionary *storeHashes = [storeMetadata objectForKey:@"NSStoreModelVersionHashes"];
    //NSLog(@"store metadata:%@", sourceMetadata);
    NSLog(@"store URL:%@", storeURL);
    NSLog(@"store NSStoreUUID:%@", [storeMetadata objectForKey:@"NSStoreUUID"]);
    NSLog(@"store NSStoreType:%@", [storeMetadata objectForKey:@"NSStoreType"]);
    NSSet *storeKeys = [NSSet setWithArray:[storeHashes allKeys]];

    // Determine store entities that were added, removed, and in common (to/with psc)
    NSMutableSet *addedEntities = [NSMutableSet setWithSet:pscKeys];
    NSMutableSet *removedEntities = [NSMutableSet setWithSet:storeKeys];
    NSMutableSet *commonEntities = [NSMutableSet setWithSet:pscKeys];
    NSMutableSet *changedEntities = [NSMutableSet new];
    [addedEntities minusSet:storeKeys];
    [removedEntities minusSet:pscKeys];
    [commonEntities minusSet:removedEntities];
    [commonEntities minusSet:addedEntities];

    // Determine entities that have changed (with different hashes)
    [commonEntities enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) {
        NSData *storeHash = [storeHashes objectForKey:key];
        NSEntityDescription *pscDescrip = [pscEntities objectForKey:key];
        if ( ! [pscDescrip.versionHash isEqualToData:storeHash]) {
            if (storeHash != nil && pscDescrip.versionHash != nil) {
                [changedEntities addObject:key];
            }
        }
    }];

    // Remove changed entities from common list
    [commonEntities minusSet:changedEntities];

    if ([commonEntities count] > 0) {
        NSLog(@"Common entities:");
        [commonEntities enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) {
            NSData *storeHash = [storeHashes objectForKey:key];
            NSEntityDescription *pscDescrip = [pscEntities objectForKey:key];
            NSLog(@"\t%@:\t%@", key, pscDescrip.versionHash);
        }];
    }
    if ([changedEntities count] > 0) {
        NSLog(@"Changed entities:");
        [changedEntities enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) {
            NSData *storeHash = [storeHashes objectForKey:key];
            NSEntityDescription *pscDescrip = [pscEntities objectForKey:key];
            NSLog(@"\tpsc   %@:\t%@", key, pscDescrip.versionHash);
            NSLog(@"\tstore %@:\t%@", key, storeHash);
    }];
    }
    if ([addedEntities count] > 0) {
        NSLog(@"Added entities to psc model (not in store):");
        [addedEntities enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) {
            NSEntityDescription *pscDescrip = [pscEntities objectForKey:key];
            NSLog(@"\t%@:\t%@", key, pscDescrip.versionHash);
        }];
    }
    if ([removedEntities count] > 0) {
        NSLog(@"Removed entities from psc model (exist in store):");
        [removedEntities enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) {
            NSData *storeHash = [storeHashes objectForKey:key];
            NSLog(@"\t%@:\t%@", key, storeHash);
        }];
    }

    BOOL pscCompatibile = [pscModel isConfiguration:nil     compatibleWithStoreMetadata:storeMetadata];
    NSLog(@"Migration needed? %@", pscCompatibile?@"no":@"yes");

    return pscCompatibile;
}

utilisation: appelé avant d'ajouter chaque magasin à NSPersistentStoreCoordinator:

    [self comparePersistentStore:self.psc withStoreURL:self.iCloudStoreURL];
    _iCloudStore = [self.psc addPersistentStoreWithType:NSSQLiteStoreType
                                          configuration:nil
                                                    URL:self.iCloudStoreURL
                                                options:options
                                                  error:&localError];
11
Symmetric

Chaque fois que vous modifiez la définition de Core Date, vous devez supprimer les applications installées sur le périphérique physique ou le simulateur.

10
pierrotlefou
  1. Arrêtez l'application de courir.
  2. Supprimer l'application sur le simulateur.
  3. Product -> Clean
  4. Construire, courir.
9
Tom Howard

La solution la plus simple qui a fonctionné pour moi dans Swift 2.1, Xcode 7 est la suivante:

  1. Supprimez l'application du simulateur (Cmd + Maj + H pour accéder à l'écran d'accueil. Appuyez longuement sur l'application, cliquez sur croix, comme vous le feriez pour supprimer une application de votre téléphone).

  2. Cmd + Shift + H à nouveau pour arrêter la danse des applications

  3. Retournez à votre projet et recommencez

J'ai eu ce problème lors de l'écriture/lecture de Core Data avec 2 entités mises en place. La suppression de l'application et la réexécution du programme ont résolu le problème.

7
Naishta

Si vous utilisez Swift.

Suivez la réponse de @Stas et insérez les options, à la place de nil, dans votre délégué d'application:

let myOptions = [NSMigratePersistentStoresAutomaticallyOption: true,
            NSInferMappingModelAutomaticallyOption: true]
        if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: myOptions, error: &error) == nil {
6
JZ.

Je viens de supprimer le fichier [Simulator App Folder]/Document/*.sqlite après avoir apporté des modifications aux entités et cela a fonctionné. Et bien sûr, le fichier .sqlite contient toutes les données et structures stockées qui seront perdues.

6
AHHP

Supprimez une application du simulateur, nettoyez un code et exécutez .it fonctionne correctement .il peut vous aider.

6
sarit bahuguna

Essayez "Réinitialiser le contenu et les paramètres" dans le simulateur. A travaillé pour moi après la suppression de l'application et de la construction propre

5
Josh10

J'ai rencontré le même problème avec mon application (pas encore publié dans l'App Store).

Voici comment je l'ai corrigé:

  1. Run Clean (Cmd + Shift + K)
  2. Redémarrer le simulateur iOS
  3. simulateur iOS -> Réinitialiser le contenu et les paramètres (à partir de la barre de navigation)

(3) fut l'étape qui l'a finalement fait fonctionner correctement. J'espère que cela t'aides!

4
bigtex777

Si vous apportez des modifications à votre modèle Core Data, vous devez fournir une stratégie de migration qui indique à Core Data comment adopter des objets persistants existants (créés par vos utilisateurs avec la version actuellement publiée) dans le nouveau modèle.

Pour certains scénarios, Core Data peut déduire automatiquement le mappage de l’ancien modèle sur le nouveau. Pour des modifications plus complexes, vous devrez peut-être implémenter une logique effectuant la migration.

Pour plus de détails, reportez-vous à la section Guide de programmation de la migration des données et du modèle de données de base .

Mettre à jour
Cette réponse ici sur Stack Overflow couvre les bases de la migration légère de Core Data et contient également du code pour vous aider à démarrer.

2
Thomas Zoechling

Bien que vous puissiez parfois simplement supprimer l'application du périphérique lors de la modification du schéma dans le modèle d'objet géré, dans certains cas, cela n'est pas possible, par exemple. parce que vous avez déjà publié votre application avec un vieux schéma.

Si tel est le cas, vous devez prendre en charge la migration des anciennes données vers le nouveau schéma:

versioning du modèle de données de base et migration des données

2
Mike

Vous devrez migrer le modèle Core Data à l'aide de la migration. Chaque fois que vous modifiez le modèle, vous le rendez incompatible avec le versioning. Attachez-vous, c'est un sujet un peu poilu.

http://developer.Apple.com/library/ios/#documentation/cocoa/Conceptual/CoreDataVersioning/Articles/Introduction.html

2
nevan king

Tout d’abord, les fichiers xcdatamodeld ne doivent figurer que dans l’ensemble xcdatamodel. Vos sous-classes doivent PAS être dans le xcdatamodeld. Déplacez ceux-ci. Il y a de fortes chances qu'ils confondent le compilateur.

Deuxièmement, l'erreur indique que Core Data ne peut pas trouver votre modèle. Avez-vous créé des données et ensuite touché le modèle? Si c'est le cas, vous êtes dans un état incohérent et vous devez résoudre ce problème en supprimant les données (ce que Philippe a suggéré) ou en lançant vos modifications du modèle BACK.

1
Marcus S. Zarra

Ce problème se produit généralement en raison de incompatibilité entre la version sur laquelle la base de données a été créée. L'approche générale à ce problème consiste à supprimer l'application et la réinstaller. Mais dans votre cas, les versions de DB sont complètement différentes sur Xcode 3.2 et 4.2. Il vaut donc mieux utiliser la même version de Xcode pour DB.

1
Jayprakash Dubey

J'ai eu ce problème - j'ai d'abord réinitialisé mon simulateur puis nettoyé le projet et reconstruit. Et puis ça marche.

0
Yashu

Lorsque vous modifiez des données de base (ajout d'un champ à une table, suppression d'un champ, etc.), le fichier sqlite du dossier du document d'applications doit être synchronisé avec votre schéma.

Ce fichier n'est pas écrasé par défaut, ce fichier doit être régénéré.

Suivez ces étapes:

  1. Allez dans le dossier indiqué par NSURL. (Ce chemin peut être trouvé dans le message d'exception généré par l'application avant la panne.) Exemple:/Utilisateurs // Bibliothèque/Application Support/iPhone Simulator // Applications // Documents

  2. supprimer ou renommer le fichier sqlite

  3. Nettoyer et réexécuter l'application
  4. L'exécution de l'application générerait un nouveau fichier sqlite.

Cela garantira que le schéma et Xcode sont synchronisés.

0
Prashant Nidgunde

J'obtenais l'erreur mais la raison pour laquelle j'ai eu l'erreur était due à ce qui suit.

À l'origine, j'avais une entité nommée "Entrée" et une ligne était enregistrée pour cette entité dans la base de données. J'ai ensuite ajouté une autre entité nommée "Personne" et après l'ajout, je suis allée construire et j'ai eu l'erreur. J'ai donc résolu le problème en supprimant l'entité "Personne" puis en construisant l'application, supprimé la ligne qui se trouvait dans "Entrée", puis fermé l'application. J'ai ensuite supprimé complètement l'application de mon téléphone, puis je l'ai reconstruite et tout a bien fonctionné. Vous ne savez pas quelle étape a corrigé le problème (suppression de la ligne ou de l'application), mais j'espère que si vous cherchez une solution, cela vous aidera. :)

Edit: Oh, et si vous vous inquiétiez de la suppression de votre nouvelle entité (dans mon cas, "Personne") pour reconstruire l'application, rappelez-vous que vous pouvez la récupérer par la suite en utilisant CMD + Z!

0
daveomcd