10 votes

Comment fusionner les changements d'un contexte d'objet géré enfant à un autre via un MOC parent ?

Bonjour (question réelle au bas de la page).

Dans iOS 5, il y a l'introduction des contextes d'objets gérés parent-enfant dans CoreData.

J'ai un NSFetchedResultsController et un UITableVeiwController standard qui travaillent ensemble pour extraire une liste principale du magasin. Le contexte d'objet géré du contrôleur de résultats récupérés est un enfant avec un contexte parent :

// AppDelegate.m

- (NSManagedObjectContext *)managedObjectContext
{
    if (__managedObjectContext != nil)
    {
        return __managedObjectContext;
    }

    __managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];

    // primary managed object context has NSPrivateQueueConcurrencyType
    [__managedObjectContext setParentContext:[self primaryObjectContext]];
    return __managedObjectContext;
}

Le contrôleur d'affichage de la table présente un contrôleur d'affichage modal pour ajouter un nouvel enregistrement, mais utilise un contexte d'objet géré distinct pour le faire (ce contexte est un autre enfant du contexte parent). Ce contexte est enregistré dans un appel de délégué dans le contrôleur de la vue tableau :

- (void)addGame
{
    // New child context

    [self setBuildManagedObectContext:[[NSManagedObjectContext alloc] init]];
    [[self buildManagedObectContext] setParentContext:[[[self team] managedObjectContext] parentContext]];

    Team *buildTeam = (Team *)[[self buildManagedObectContext] objectWithID:[[self team] objectID]];
    Game *buildGame = [NSEntityDescription insertNewObjectForEntityForName:@"Game" 
                                                inManagedObjectContext:[self buildManagedObectContext]];

    [buildGame setTeam:buildTeam];

    BuildViewController *buildVC = [[BuildViewController alloc] initWithGame:buildGame delegate:self];
    UINavigationController *navCon = [[UINavigationController alloc] initWithRootViewController:buildVC];
    [[self navigationController] presentViewController:navCon animated:YES completion:nil];
}

#pragma mark - Build view controller delegate

- (void)buildViewController:(BuildViewController *)controller didFinishWithSave:(BOOL)save
{
    if (save)
    {
        NSError *error = nil;
        if (![[self buildManagedObectContext] save:&error])
        {
            NSLog(@"Error saving new game");
            abort();
        }
    }
    [self setBuildManagedObectContext:nil];
    [[self navigationController] dismissViewControllerAnimated:YES completion:nil];
}

Question :

Je croyais qu'avec les contextes parent-enfant, le contexte parent recevait la notification de sauvegarde de son enfant, puis notifiait tous ses enfants. Ainsi, dans mon exemple, le contexte de construction devrait demander au contexte parent de dire au contrôleur des résultats récupérés de fusionner les changements.

Ce n'est pas ce qui se passe pour moi, les enregistrements sont créés avec succès, mais le contrôleur des résultats récupérés ne les récupère pas. Je sais qu'auparavant, il fallait implémenter sa propre fusion à partir de la notification de sauvegarde (comme dans l'exemple ci-dessous). CoreDataBooks ). Mais je pensais que les contextes enfant-parent avaient résolu ce problème. J'ai essayé d'enregistrer l'enfant, puis le parent, mais cela ne semble pas faire de différence. Quelqu'un peut-il m'expliquer ce problème ? (Note : Il ne s'agit pas de contextes sur des fils séparés/arrière-plan)

Merci beaucoup

14voto

afrederick Points 736

Selon la présentation WWDC 2011 de "What's new in Core Data", il est indiqué que vous devez enregistrer comme ceci :

[child save:&error]; 
[parent performBlock:^{
    [parent save:&parentError];
}];

D'après ce que j'ai compris, cela permet au parent de recevoir et de fusionner les modifications du contexte enfant. Une chose à noter est que le parent et tous les enfants doivent être créés avec le même type de concurrence.

-- Editer a supprimé l'hypothèse incorrecte que le parent pousse les changements aux enfants, il ne le fait pas.

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