保存时的 NSManagedObjectContext 层次结构

Posted

技术标签:

【中文标题】保存时的 NSManagedObjectContext 层次结构【英文标题】:NSManagedObjectContext hierarchy when saving 【发布时间】:2014-06-13 15:34:18 【问题描述】:

我见过一些例子,你会这样做:

_model = [NSManagedObjectModel mergedModelFromBundles:nil];
_coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:_model];

_context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; // THIS IS THE MAIN CONTEXT
[_context setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];

_childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_childContext performBlockAndWait:^
    [_childContext setParentContext:_context];
    [_childContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
    [_childContext setUndoManager:nil]; 
];

然后您可以在视图的子上下文中插入一个项目,通常是模态视图。当用户点击取消时,该对象仅在子上下文中并且在那一刻永远不会被保存,因此很容易创建临时 NSManagedObjects 并丢弃它们,直到您保存两个上下文。你有什么理由不能这样做:

_parentContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_parentContext performBlockAndWait:^
    [_parentContext setPersistentStoreCoordinator:_coordinator];
    [_parentContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
];

_context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_context setParentContext:_parentContext];
[_context setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];

现在您将内容插入到 parentContext 中。然后当你保存时,你首先保存_context(主上下文),然后它会冒泡到parentContext?它似乎在代码中工作,但我不知道是否有原因为什么我看到的示例都将对象插入到主要上下文是父上下文的 childContext 中。

或者有没有更好的方法来处理点击添加项目的用例,显示一个模式视图,其中包含为此视图创建的新 NSManagedObject。这就是我看到的大部分示例代码在显示“添加项目”视图时创建一个新项目的方式。问题是如果你点击添加项目,点击取消,然后再次点击添加项目,你现在会有两个 NSManagedObjects 在上下文中浮动。

【问题讨论】:

【参考方案1】:

Apple 建议保存到磁盘的上下文为 NSMainQueueConcurrencyType 类型,这也适用于 UI 操作,例如获取和显示。其原因尚不清楚,但根据经验,您应该真正遵循这一点,因此您的主要上下文类型为NSMainQueueConcurrencyType

现在,如果您将对象添加到父上下文,这些更改不会冒泡 到子上下文。这就是为什么您总是希望数据流向主上下文并插入子上下文的原因。在您的第二个示例中,如果您将对象添加到 _parentContext,但您的 UI 正在侦听 _context 上的更改,则它不会听到正在添加的新对象或正在更改的对象。

注意,如果您打算创建一个临时子上下文来将数据传入和传出 UI,请将上下文创建为并发类型为 NSMainQueueConcurrencyType 的子上下文,这样您就可以直接从主线程设置属性,而不是让给performBlock:他们。

我目前的方法不是创建上下文并直接使用对象,而是使用字典并将我的数据“绑定”到它。只有在用户保存后,我才会创建一个新对象,将数据从字典中传输到对象并保存。不确定这是否真的重要,因为子/父上下文使这种一次性操作变得非常便宜和容易。

【讨论】:

以上是关于保存时的 NSManagedObjectContext 层次结构的主要内容,如果未能解决你的问题,请参考以下文章

同步保存到 parse.com 时的进度条

保存时的 NSManagedObjectContext 层次结构

取消保存对话框时的SaveFileDialog错误

RStudio - 保存环境时的压缩

保存数据时的AssociationTypeMismatch问题

保存文件时的 XLSX 语言环境