50 votes

Mise en œuvre de la "migration légère automatique" pour Core Data (iPhone)

Je voudrais faire de mon appli capable de faire automatiquement un léger migration lorsque je ajouter de nouveaux attributs à ma base de données modèle.

Dans le guide d'Apple c'est la seule info sur le sujet, j'ai pu trouver:

Automatique Léger Migration

Pour demander automatique léger la migration, vous définissez les options appropriées dans les options du dictionnaire que vous transmettez addPersistentStoreWithType:configuration:URL:options:erreur:. Vous devez définir les valeurs correspondantes à la fois à l' NSMigratePersistentStoresAutomaticallyoption et la NSInferMappingModelAutomaticallyoption clés pour OUI:

NSError *error;
NSURL *storeURL = <#The URL of a persistent store#>;
NSPersistentStoreCoordinator *psc = <#The coordinator#>;
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
    [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
    [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

if (![psc addPersistentStoreWithType:<#Store type#>
    configuration:<#Configuration or nil#> URL:storeURL
    options:options error:&error]) {
    // Handle the error.
}

Mon NSPersistentStoreCoordinator est initialisé de la façon suivante:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

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

    NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"FC.sqlite"]];

    NSError *error = nil;
    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }    

    return persistentStoreCoordinator;
}

J'ai du mal à voir où et comment je dois ajouter la Pomme de code pour obtenir l'Automatique Léger de la Migration de travail?

93voto

willi Points 3773

C'est ce que j'ai fait pour le rendre Automatique Léger Migration (Source: http://brainwashinc.wordpress.com/2010/01/18/iphone-coredata-automatic-light-migration/)

1. Définir la persistance de Stocker les options de migration automatique dans l'application délégué.

Changer votre persistentStoreCoordinator création de ce (remplacer YOURDB):

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

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

  NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"YOURDB.sqlite"]];

  // handle db upgrade
  NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
  [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
  [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

  NSError *error = nil;
  persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
  if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
    // Handle error
  }

  return persistentStoreCoordinator;
}

2. La Version de votre Modèle de Données et de Modifier le nouveau fichier.

Sélectionnez votre fichier xcdatamodel Conception -> Modèle de Données -> Ajouter Version du Modèle (développez votre xcdatamodeld élément) Sélectionnez "2" (ou ultérieure) du fichier, la Conception -> Modèle de Données> Définir la Version Actuelle (modifier la présente version)

3. Spécifiez le momd ressource délégué d'application.

Changer votre managedObjectModel mise en œuvre de cette (remplacer YOURDB)

- (NSManagedObjectModel *)managedObjectModel {

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

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

  return managedObjectModel;
}

7voto

udibr Points 147

Au premier abord, la solution ci-dessus ne fonctionne pas pour moi. Le retour de l'managedObjectModel était 0x0. Je pense que c'est parce que j'ai renommé le fichier des noms des différents fichiers de modèle. Si vous suivez les instructions ci-dessus à la lettre alors que tout fonctionne.

Toutefois, si vous n'modèle de changement de noms de fichier vous pouvez sélectionner le "en cours" modèle de fichier manuellement: Disons que votre modèle d'origine du fichier a été MONMODÈLE.xcdatamodel après avoir fait le complément du modèle de l'étape au-dessus de ce qui se transforme en un répertoire de MON.xcdatamodeld et en dessous vous avez MONMODÈLE.xcdatamodel et MONMODÈLE 2.xcdatamodel renommer le nouveau fichier de modèle de ce que vous voulez, par exemple, disons que vous avez supprimé l'espace de MYMODEL2.xcdatamodel et modifier son contenu. Maintenant, dans le code ci-dessus ne

NSString *path = [mainBundle pathForResource:@"MYMODEL2" ofType:@"mom" inDirectory:@"MYMODEL.momd"];

1voto

Chris Prince Points 798

Je pense que cela ajoute à la dernière réponse.

J'ai trouvé l'utilisation de l'ensemble des ressources et des .sqlite noms vraiment déroutant au premier abord. Le bundle de ressources changement de nom avec le changement de version? L' .sqlite changement de nom? J'ai reçu aujourd'hui ma migration de travail, et appris que le bundle nom du modèle désigne le nom du répertoire/dossier dans XCode contenant tous les modèles, pas le nom du modèle de versions à l'intérieur de ce répertoire.

Quand vous donnez un modelResource nom de:

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:modelResource withExtension:@"momd"];
NSManagedObjectModel *theManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

Que modelResource nom est le répertoire/dossier pour les modèles dans Xcode.

Lorsque vous faites:

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:storeFileName];
    NSError *error = nil;

    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
        // handle error
    }

Le storeFileName est le nom de votre .sqlite fichier dans le dossier Documents/répertoire (c'est pas dans le bundle).

Aussi, lorsque vous effectuez une migration à partir d'un modèle à un autre modèle, la version, par défaut, l' .sqlite nom du fichier reste le même.

0voto

GeM Points 71

Oscar, en réponse à ton problème, j'ai trouvé la même chose au départ. Je suggère de supprimer et d'ajouter de nouveau le nouveau fichier .xcdatamodeld à votre projet, puis de le reconstruire. J'espère que cela pourra aider!

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