45 votes

Migration légère d'un document NSPersistent

Je suis en train de faire un léger migration de SQLite stocker dans la Base de Données. Travail sur Lion 10.7.3 avec Xcode 4.3.1.

Dans mon NSPersistentDocument sous-classe (AccountDocument), j'ai surchargé la méthode utilisée pour configurer le système de persistance coordonnateur de sorte qu'il obtient 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)

Quand je lance l'application, il échoue dans NSPersistentDocument mise en œuvre de l' -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

De ce que je peux dire à partir de la documentation, la mise en œuvre par défaut ressemble à quelque chose comme ceci:

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

Afin de déboguer le problème un peu plus, j'ai remplacé cette méthode avec 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 les url pointent vers les endroits que j'attends (et je l'ai suivie Marcus Zarra conseils pour nettoyer le projet, alors il n'y a pas de parasite .maman ou .momd faisceaux dans l'ensemble de la demande: à l'Aide de mergedModelFromBundles: and versioning (CoreData)). Pourtant, l'application continue d'un crash lors du chargement du modèle à partir de l'url.

J'ai vérifié que le AccountDocument2.xcdatamodeld est un package qui a deux modèles pour la gestion des versions: AccountDocument 2.xcdatamodel et (l'original) AccountDocument.xcdatamodel. Le "sans version de Base du Modèle de Données" popup menu dans les propriétés du fichier est réglé sur "AccountDocument 2".

La seule différence entre les deux modèles est qu'une Entité a une (et facultatif) Attribut. Ma compréhension est que qualifie le modèle pour un poids léger de la migration.

Évidemment, je suis en train de faire quelque chose de mal ici, mais je n'ai aucune idée de ce qu'. Toute aide serait grandement appréciée...

Mise à jour:

Par Martin suggestion (et une vérification de la NSPersistentDocument documentation) 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;
}

Plante toujours...

Mise à jour

Après quelques suggestions sur Twitter, j'ai mis à jour de Xcode 4.3.2, mais les problèmes persistent.

LA RAGE DE MISE À JOUR

Je viens de créer la version du modèle de colis (AccountDocument2.xcdatamodeld) à l'aide de Xcode 4.2 sur Snow Leopard. Après la création et l'exécution de l'application, tout fonctionne comme prévu.

J'ai ensuite pris la AccountDocument2.xcdatamodeld fichier de package de Lion et Xcode 4.3.2. Lorsque je créer et exécuter l'application, il continue à se bloquer pendant le chargement de la .momd de ressources. Oui les enfants, cela signifie que Xcode 4.3.x et le Modèle de Données Compilateur (MOMC) sont à blâmer. Je ne vois pas de solution autre que de faire tous mes s'appuie sur Snow Leopard.

Je ne suis pas un bash Xcode 4, mais lorsque nous nous trouvons dans une situation où la chaîne ne peut pas produire un opaque fichier (.et maman .momd) à partir d'un opaque spécification.xcdatamodel et .xcdatamodeld) il est assez difficile d'être optimiste à propos de l'état de Mac et iOS outils. Il est ridicule que, une composante essentielle de ces plates-formes pauses au degré où je ne peux pas générer et exécuter mon application sur la dernière version du SDK et outils de développement.

Il est Venu À Cette mise à Jour

Preuve de plus que c'est un sérieux problème avec le Modèle de Données Compilateur (MOMC) dans Xcode 4.3.2: si je copie le .momd bundle à partir de la Ressource dossier créé par Xcode 4.2 dans mon projet et de les ajouter à la construire en tant que Copie des Fichiers phase de construction, l'application fonctionne très bien.

J'ai aussi fait des tests où j'ai enlevé les règles de validation et valeurs par défaut pour les Attributs des diverses Entités (basé sur Marcus suggestion ci-dessous.) Pas de changement, le compilateur crée toujours valide .momd. J'ai aussi essayé de créer un versionnées modèle où RIEN n'a été changé: la compilation .momd suite à l'incident. 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 bug n'est pas isolé à NSPersistentDocument (que je pensais quand j'ai commencé cette question.) Je peut provoquer une appli crash en utilisant simplement [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL].

Pour l'instant, je vais modifier/versioning mes modèles à l'aide de Xcode 4.2 sur Snow Leopard et le déplacement de la compilation de ressources Xcode 4.3.2 sur Lion. Si vous utilisez la Base de Données de quelque sorte, je vous suggère de faire la même chose jusqu'à ce que ce bug est adressée. Faites-moi confiance, vous allez passer des jours à essayer de comprendre ce que l'enfer qui se passe si vous ne le faites pas.

Maintenant soumettre un Radar...

Radar De Mise À Jour

Je viens d'envoyer ce Radar:

http://www.openradar.me/11184500

Oh Merde Elle Doit Être Mise À Jour De Lion

J'ai juste téléchargé et installé Xcode 4.2 pour le Lion d'outils de http://developer.apple.com/downloads. L'exemple de l'application utilisée dans le Radar se bloque toujours.

(Remarque: vous ne pouvez pas installer Xcode 4.2.1 parce que le certificat utilisé pour signer le DeveloperTools.pkg a expiré. Seulement Xcode 4.2 fonctionnent.)

Si vous êtes en vertu de la LDN, vous trouverez également que la beta outils ne sont pas très utile.

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

Le WTF Faire Extraire les Demandes Ont À Faire Avec de version des Entités et des Attributs de mise à Jour

Via Evadne Wu sur Twitter:

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

Et comment elle a fait:

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

(.maman fichiers sont binaires plists.)

La racine du problème est une seule Demande de récupération. Comment dans une migration de données à partir d'un modèle à l'autre est pour un ingénieur de chez Apple à la figure.

11voto

chockenberry Points 5518

La compilation .momd ressources peuvent être chargés après un "existingPartner" extraire la demande est modifié à partir de:

name == $name

pour:

name == $NAME

C'est contre-intuitif qu'une partie du modèle objet qui n'a pas d'incidence sur la persistance de données des pauses de contrôle de version et léger de la migration. Il est clair à partir de la documentation que cela ne devrait pas être le cas:

Base de Données de point de vue sur la gestion des versions est qu'il est seulement intéressé par les caractéristiques du modèle qui affectent la persistance.

Utiliser la puissance de la CHOCKLOCK pour fixer votre Extraction de Demandes ou de les supprimer complètement, et de s'appuyer sur NSPredicates créé dans le code.

1voto

Martin Pilkington Points 2355

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

1voto

Marcus S. Zarra Points 32178

En vous basant sur votre théorie selon laquelle il s'agit d'un problème avec le MOMC, avez-vous des règles de validation dans la mère?

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

0voto

Z S Points 1339

Cela pourrait être un peu lié à un problème lié à l'utilisation de requêtes d'extraction 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 requête d'extraction, je l'ai donc supprimée et tout fonctionnait bien: avertissement Core Data: "Les informations de hachage de version ne sont pas disponibles pour tous les modèles"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X