Как объединить изменения одного контекста управляемого объекта с другим через родительский MOC? - PullRequest
9 голосов
/ 20 марта 2012

Здравствуйте (актуальный вопрос внизу).

В iOS 5 введены контексты родительских и управляемых объектов в CoreData.

У меня есть стандартный NSFetchedResultsController и UITableVeiwController, работающие вместе, чтобы получить основной список из магазина. Выбранный контекст управляемого объекта контроллера результатов является дочерним с родительским контекстом:

// 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;
}

Контроллер табличного представления представляет модальный контроллер представления для добавления новой записи, но для этого использует отдельный контекст управляемого объекта (этот контекст является другим дочерним по отношению к родительскому контексту). Этот контекст сохраняется в обратном вызове делегата в контроллере табличного представления:

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

Вопрос:

Насколько я понимаю, в контексте родительских и дочерних элементов родительский контекст получит уведомление о сохранении от своего дочернего элемента, а затем уведомит всех своих дочерних элементов. Так что в моем примере контекст сборки должен запускать родительский контекст, чтобы сообщить извлеченному контроллеру результатов о слиянии изменений.

Это не происходит для меня, записи успешно созданы, но контроллер извлеченных результатов не собирает их. Я знаю, что раньше вам приходилось реализовывать собственное слияние из уведомления о сохранении (как видно из CoreDataBooks ). Но я думал, что контексты ребенка-родителя решили эту проблему. Я пытался спасти ребенка, а затем родителя, но, похоже, ничего не изменилось. Может кто-нибудь объяснить это мне, пожалуйста? (Примечание: это не контексты в отдельных / фоновых потоках)

Большое спасибо

1 Ответ

14 голосов
/ 20 марта 2012

В соответствии с презентацией WWDC 2011 «Что нового в базовых данных» говорится, что вы должны сохранить как это:

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

Насколько я понимаю, это заставляет родителя получать и объединять изменения из дочернего контекста. Следует отметить, что родитель и все дочерние элементы должны быть созданы с одним и тем же типом параллелизма.

- Редактировать удалено неверное предположение о том, что родительский элемент передает изменения дочерним элементам, но не делает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...