objective c - Migration légère d'un document NSPersistentDocument

Translate

J'essaie de faire une migration légère d'un magasin SQLite dans Core Data. Travailler sur Lion 10.7.3 avec Xcode 4.3.1.

Dans ma sous-classe NSPersistentDocument (AccountDocument), j'ai remplacé la méthode utilisée pour configurer le coordinateur de magasin persistant afin qu'il obtienne les options appropriées pour la migration:

- (BOOL)configurePersistentStoreCoordinatorForURL:(NSURL *)url ofType:(NSString *)fileType modelConfiguration:(NSString *)configuration storeOptions:(NSDictionary *)storeOptions error:(NSError **)error
{
    NSMutableDictionary *newStoreOptions;
    if (storeOptions == nil) {
        newStoreOptions = [NSMutableDictionary dictionary];
    }
    else {
        newStoreOptions = [storeOptions mutableCopy];
    }
    [newStoreOptions setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
    [newStoreOptions setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];

    BOOL result = [super configurePersistentStoreCoordinatorForURL:url ofType:fileType modelConfiguration:configuration storeOptions:newStoreOptions error:error];
    return result;
}

(Merci à Malcolm Crawford pour cette astuce:http://homepage.mac.com/mmalc/CocoaExamples/controllers.html)

Lorsque j'exécute l'application, elle échoue dans l'implémentation de NSPersistentDocument de-managedObjectModel:

* thread #1: tid = 0x2703, 0x00007fff931d9350 libobjc.A.dylib`objc_msgSend_vtable13 + 16, stop reason = EXC_BAD_ACCESS (code=13, address=0x0)
    frame #0: 0x00007fff931d9350 libobjc.A.dylib`objc_msgSend_vtable13 + 16
    frame #1: 0x00007fff8935e975 CoreData`-[NSKnownKeysDictionary1 _setValues:retain:] + 197
    frame #2: 0x00007fff8935f288 CoreData`_newReadModelFromBytes + 648
    frame #3: 0x00007fff8935b93e CoreData`+[NSManagedObjectModel(_NSManagedObjectModelPrivateMethods) _newModelFromOptimizedEncoding:error:] + 9310
    frame #4: 0x00007fff89359451 CoreData`-[NSManagedObjectModel(_NSManagedObjectModelPrivateMethods) initWithContentsOfOptimizedURL:] + 305
    frame #5: 0x00007fff89358d7b CoreData`-[NSManagedObjectModel initWithContentsOfURL:] + 443
    frame #6: 0x00007fff893e9519 CoreData`+[NSManagedObjectModel mergedModelFromBundles:] + 377
    frame #7: 0x00007fff8ded7037 AppKit`-[NSPersistentDocument managedObjectModel] + 301
    frame #8: 0x00007fff8ded70b3 AppKit`-[NSPersistentDocument managedObjectContext] + 75
    frame #9: 0x00007fff8ded6e3f AppKit`-[NSPersistentDocument _persistentStoreCoordinator] + 18
    frame #10: 0x00007fff8ded6b5d AppKit`-[NSPersistentDocument configurePersistentStoreCoordinatorForURL:ofType:modelConfiguration:storeOptions:error:] + 51
    frame #11: 0x0000000100003193 BeanCounter`-[AccountDocument configurePersistentStoreCoordinatorForURL:ofType:modelConfiguration:storeOptions:error:] + 419 at AccountDocument.m:298

D'après ce que je peux dire de la documentation, l'implémentation par défaut ressemble à ceci:

- (id)managedObjectModel
{
    NSManagedObjectModel *result = [NSManagedObjectModel mergedModelFromBundles:nil];
    return result;
}

Donc, pour déboguer un peu plus le problème, j'ai remplacé cette méthode par ceci:

- (id)managedObjectModel
{
    NSBundle *bundle = [NSBundle mainBundle];
    NSURL *url = [bundle URLForResource:@"AccountDocument2" withExtension:@"momd"];
    NSManagedObjectModel *result = [[[NSManagedObjectModel alloc] initWithContentsOfURL:url] autorelease];  
    return result;
}

(Merci à Jeff LaMarche pour l'idée:http://iphonedevelopment.blogspot.com/2009/09/core-data-migration-problems.html)

Le bundle et l'url pointent tous les deux vers les endroits que j'attends (et j'ai suivi les conseils de Marcus Zarra pour nettoyer le projet afin qu'il n'y ait pas de bundles .mom ou .momd errants dans le package d'application:Utilisation de mergedModelFromBundles: et gestion des versions (CoreData)). Pourtant, l'application continue de planter lors du chargement du modèle à partir de l'URL.

J'ai vérifié que AccountDocument2.xcdatamodeld est un package qui a deux modèles de contrôle de version: AccountDocument 2.xcdatamodel et (l'original) AccountDocument.xcdatamodel. Le menu contextuel "Modèle de données de base versionné" dans les propriétés du fichier est défini sur "AccountDocument 2".

La seule différence entre les deux modèles est qu'une entité possède un attribut supplémentaire (et facultatif). Je crois comprendre que cela qualifie le modèle pour une migration légère.

De toute évidence, je fais quelque chose de mal ici, mais je ne sais pas quoi. Toute aide serait appréciée…

Mettre à jour:

Selon la suggestion de Martin (et une vérification de la documentation NSPersistentDocument), j'ai essayé d'utiliser ce code pour l'accesseur:

- (id)managedObjectModel
{
    static id sharedManagedObjectModel = nil;

    if (sharedManagedObjectModel == nil) {
        NSBundle *bundle = [NSBundle mainBundle];
        NSURL *url = [bundle URLForResource:@"AccountDocument2" withExtension:@"momd"];
        sharedManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:url];
    }

    return sharedManagedObjectModel;
}

Toujours en panne…

Mettre à jour

Après quelques suggestions sur Twitter, je suis passé à Xcode 4.3.2, mais les problèmes persistent.

MISE À JOUR DE RAGE

Je viens de créer le package de modèle versionné (AccountDocument2.xcdatamodeld) en utilisant Xcode 4.2 sur Snow Leopard. Après avoir créé et exécuté l'application, tout fonctionne comme prévu.

J'ai ensuite repris le package de fichiers AccountDocument2.xcdatamodeld vers Lion et Xcode 4.3.2. Lorsque je crée et exécute l'application, elle continue de se bloquer lors du chargement de la ressource .momd. Oui les enfants, cela signifie que Xcode 4.3.x et le Data Model Compiler (MOMC) sont à blâmer. Je ne vois pas de solution de contournement autre que de faire toutes mes constructions sur Snow Leopard.

Je ne suis pas du genre à bash Xcode 4, mais lorsque nous nous trouvons dans une situation où la chaîne d'outils ne peut pas produire un fichier opaque (.mom et .momd) à partir d'une spécification opaque (.xcdatamodel et .xcdatamodeld), il est assez difficile de soyez optimiste quant à l'état des outils Mac et iOS. Il est ridicule qu'un composant de base de ces plates-formes tombe au point de ne pas pouvoir créer et exécuter mon application sur la dernière version du SDK et des outils de développement.

C'est venu à cette mise à jour

Plus de preuve qu'il s'agit d'un bug sérieux avec le Data Model Compiler (MOMC) dans Xcode 4.3.2: si je copie le bundle .momd du dossier Resource créé par Xcode 4.2 dans mon projet et les ajoute à la construction en tant que Copy Files phase de construction, l'application fonctionne très bien.

J'ai également fait quelques tests où j'ai supprimé les règles de validation et les valeurs par défaut pour les attributs des différentes entités (basé sur la suggestion de Marcus ci-dessous.) Pas de changement, le compilateur crée toujours un .momd invalide. J'ai également essayé de créer un modèle versionné où RIEN n'a été changé: le .momd compilé a continué à planter. Donc, tout ce que vous avez dans vos modèles actuels (et les données qu'ils représentent) est la source du problème.

À noter également: ce bogue n'est pas isolé de NSPersistentDocument (comme je le pensais à l'origine lorsque j'ai commencé cette question.) Je peux provoquer le blocage d'une application en utilisant simplement[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL].

Pour l'instant, je vais éditer / versionner mes modèles en utilisant Xcode 4.2 sur Snow Leopard et déplacer les ressources compilées vers Xcode 4.3.2 sur Lion. Si vous utilisez Core Data de quelque manière que ce soit, je vous suggère de faire de même jusqu'à ce que ce bogue soit résolu. Croyez-moi, vous passerez des jours à essayer de comprendre ce qui se passe si vous ne le faites pas.

Maintenant, pour soumettre un radar…

Mise à jour du radar

Je viens de soumettre ce radar:

http://www.openradar.me/11184500

La mise à jour Oh Crap It Must Be Lion

Je viens de télécharger et d'installer les outils Xcode 4.2 pour Lion à partir dehttp://developer.apple.com/downloads. L'exemple d'application utilisé dans le radar plante toujours.

(Remarque: vous ne pouvez pas installer Xcode 4.2.1 car le certificat utilisé pour signer DeveloperTools.pkg a expiré. Seul Xcode 4.2 fonctionnera.)

Si vous êtes sous NDA, vous constaterez également que les outils bêta ne sont pas non plus utiles.

J'espère que vous avez une copie de Snow Leopard avec Xcode 4.2:http://furbo.org/2012/03/28/vmware-for-developers/

Les requêtes WTF Do Fetch ont à voir avec la mise à jour des entités et attributs versionnés

Via Evadne Wu sur Twitter:

https://twitter.com/#!/evadne/status/187625192342818818

Et comment elle l'a fait:

https://twitter.com/#!/evadne/status/187629091518816258

(Les fichiers .mom sont des plists binaires.)

La racine du problème est une seule demande de récupération. C'est à un ingénieur d'Apple de comprendre comment cela se traduit par une migration de données d'un modèle à un autre.

This question and all comments follow the "Attribution Required."

Toutes les réponses

Translate

Les ressources .momd compilées peuvent être chargées après la modification d'une requête d'extraction "existingPartner":

name == $name

à:

name == $NAME

Il est contre-intuitif qu'une partie du modèle objet qui n'affecte pas la persistance des données interrompt la gestion des versions et la migration légère. Il ressort clairement de la documentation que cela ne devrait pas être le cas:

Le point de vue de Core Data sur la gestion des versions est qu'il ne s'intéresse qu'aux fonctionnalités du modèle qui affectent la persistance.

Utilisez la puissance duCHOCKLOCKpour corriger vos demandes de récupération ou les supprimer complètement et compter surNSPredicates créés dans le code.

La source
Translate

Je pense que vous devez stocker le modèle d'objet géré dans une variable d'instance. Vous renvoyez un objet libéré automatiquement, ce qui est probablement à l'origine du mauvais accès.

La source
Translate

Sur la base de votre théorie selon laquelle c'est un problème avec le MOMC, avez-vous des règles de validation chez la mère?

J'ai vu des rapports où les règles de validation ne survivent pas au MOMC 4.x.

La source
Z S
Translate

Cela pourrait être en quelque sorte lié à un problème que j'ai rencontré lors de l'utilisation des demandes de récupération lorsque iOS5 est sorti pour la première fois en version bêta. Cela provoquait un avertissement de construction et plantait l'application au lancement. Je n'utilisais pas vraiment la demande de récupération, je l'ai donc supprimée et tout a bien fonctionné:Avertissement relatif aux données de base: "Informations de hachage de version non disponibles pour tous les modèles"

La source
Leave a Reply
You must be logged in to post a answer.
A propos de l'auteur