【问题标题】:How to merge changes from one child managed object context to another via a parent MOC?如何通过父 MOC 将更改从一个子托管对象上下文合并到另一个?
【发布时间】:2012-04-05 04:41:40
【问题描述】:

你好(实际问题在底部)。

在 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 所示)。但我认为孩子-父母的背景解决了这个问题。我试着救了孩子,然后救了父母,但似乎没有什么不同。有人可以向我解释一下吗? (注意:这些不是单独/后台线程上的上下文)

非常感谢

【问题讨论】:

    标签: objective-c core-data ios5


    【解决方案1】:

    根据 WWDC 2011 的“Core Data 中的新功能”演示文稿,它说您应该像这样保存:

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

    据我了解,这会导致父级接收并合并来自子级上下文的更改。需要注意的一点是,必须使用相同的并发类型创建父级和所有子级。

    -- 编辑删除了父级将更改推送给子级的错误假设,它没有。

    【讨论】:

    • "需要注意的一点是,必须使用相同的并发类型创建父级和所有子级。"嗯...如果你想在主线程中执行更新 MOC 并支持 UI 的后台获取数据,它们将不会是相同的并发类型???
    • @user786383 为您的并发类型使用 NSMainQueueConcurrencyType 不会对您的 UI 线程产生不利影响或阻塞。如果您使用 MOC 执行获取以更新 UI 元素(例如通过 NSFetchedResultsController 填充 UITableView),则最好使用该并发类型。
    • 父上下文不会将更改“推送”到现有子上下文。因此,如果您对子上下文 1 进行更改,保存子上下文 1 并保存父上下文,则子上下文 2 中该实体的活动实例将不会有该更改。您必须在子上下文 2 上调用 reset 并重新获取对象以查看在子上下文 1 中所做的更改。如果子上下文 2 没有实体的任何缓存实例,这不是问题,但这很重要要理解这是因为上下文在获取时从持久存储中拉,而不是因为父上下文推送到其子级。
    • @ChristopherPickslay 你是一个美丽的人。
    • @afrederick 我认为你错了。子 MOC可以与父 MOC 具有不同的并发类型:stackoverflow.com/questions/14284301/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-30
    • 2013-01-02
    • 2021-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多