2013-02-22 90 views
6

在我的应用程序中,我有UITableViewController显示事件列表。此控制器使用ManagedObjectContext说ParentContext。现在,如果选择了任何事件,则会显示详细的视图控制器,用户可以在其中编辑事件的详细信息。所以,我创建了一个孩子方面说,核心数据多级父 - 子环境

ChildContext with type "NSPrivateQueueConcurrencyType"

ChildContext whose parent Context is "ParentContext".

我的代码是:

NSManagedObjectContext *childContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
    childContext.parentContext = self.context ; 

现在再次有一些字段和关系这需要另外的向下钻取。所以我创造了另一种ChildContext新视图控制器说,

GrandChildContext with type "NSPrivateQueueConcurrencyType"

GrandChildContext whose parent context is "ChildContext"

这个过程也适用于其他级别(从父(的tableView共4级)儿童)

self.context - Parent Context 
    | 
    | 
ChildContext 
    | 
    | 
GrandChildContext 
    | 
    | 
GrandGrandChildContext 

我的实体看上去像这样

EntityA   -- (Edit View Controller - uses ChildContext) 
| 
|- Field1 
| 
|- Field2 
| 
|- RelationShip (1 to Many) - (Relationship Add/Edit View Controller - uses GrandChildContext) 
    | 
    |- Field1 
    | . 
    | . 
    |- Field3 
    | 
    |- Relationship (1 to Many) - (Relationship Add/Edit View Controller - uses GrandGrandChildContext) 
      | 
      |- Field1 
      | 
      |- Field2 

这是使用父 - 子上下文的正确方法吗?因为在某个时间点,我会像1 NSMainQueueConcurrencyType MOC and 3 NSPrivateQueueConcurrencyType MOC一样。

如果不是?有没有其他方法?

是否有太多的子上下文影响应用程序的性能?

最初我使用属性和NSArrays来管理用户输入的数据,当用户点击完成按钮时,我将更新/创建托管对象。但这是一个乏味的工作,它让我的视图控制器很脏。所以我切换到父 - 子上下文,这很容易保存/丢弃更新。

由于

回答

4

你可能已经对多个子上下文有点过分了,但只有一点儿,你的一般方法是合理的。 MOC(托管对象上下文)是一个相当轻量级的对象。

我喜欢你的方法,在每个视图控制器/场景中有独特的参考,适用于该场景的MOC。

将MOC视为会话或暂存区有时很有帮助。对决不在MOC和实体之间,而是在MOC和逻辑工作单元之间。

如果您的一个向下钻取标记了用户可能想要放弃/取消的某个编辑任务的开始,那么这是一个剥离子MOC并将其传递给新视图的好时机。如果需要的话,你可以回滚:甚至放弃MOC,当你放松回到起点时。另一方面,如果您只是为静态信息编写一个查看器,则只需使用一个MOC。在这种情况下,没有必要或从中获益更多。

+3

在所有的演习中,我都有编辑任务。我在一些钻取中设法减少了一些保存/取消操作。在使用此模型一段时间后,我发现的唯一问题是,创建的关系在父级子项中不可见。这只发生在ios 5中,这是一个已知的bug,我通过在保存子上下文之前调用obtainPermanentIDs来修复它。 – krishnan 2013-04-12 01:53:14

+0

哦,我的天啊,+ krishnan,在我发现这个注释之前,我把我的头发撕了一半,并尝试添加一个acquirePermanentIDs调用。 – 2013-07-22 15:20:23

-1

或许有关于最好使用的情况下用于嵌套管理对象的上下文混乱微量。对于你的情况,我会建议只使用一个单一的上下文。

从数组等移动到核心数据是一个非常好的主意。现在释放对象图的真正力量和简单性。尽量保持简单。

为了向下钻取,只需将上下文传递给子视图控制器。您的子视图控制器获取的结果控制器可以使用与父视图控制器相同的上下文。众多Apple代码示例正是使用这种模式。

您需要上下文的唯一时间是如果您确实需要并发性。这似乎并不是这种情况。一旦检索到数据,就会显示子视图控制器的新界面。如果这需要很长时间(比如说,因为数据来自Web服务),那么您将显示某种“请稍候”界面,并在数据检索完成后显示完整的界面。很可能这不是你的情况。

+5

如果您查看[link](https://developer.apple.com/videos/wwdc/2012/)wwdc 2012视频核心数据最佳做法会话214,它将显示如何使用父级和子级上下文显示详细信息视图控制器。我正在使用相同的技术,所以如果用户点击保存按钮,我可以保存子上下文,并且子上下文的所有更改都会被推送到父上下文。当用户点击取消按钮时,我只需关闭视图控制器,所有更改都将丢失。这里我所有的子视图控制器都是详细检查器,它使用编辑数据,所以没有提取结果控制器。 – krishnan 2013-02-23 02:07:19

+0

您可以使用'[上下文回滚];''而不是'[context save:nil];''来实现同一个上下文。如果详细视图控制器的提取会花费过多的时间,则WWDC视频非常有用。 – Mundi 2013-02-23 19:05:58

+0

我想你不理解我的问题。我的问题是类似这[一](http://stackoverflow.com/questions/10443754/undo-all-changes-made-in-the-child-view-controller)。但在我的情况下,我有多层次的儿童情况。用'[上下文回滚]'我所有的更改都将丢失。但是,我只想要放弃一些更改。我会尽快上传一个示例项目。谢谢 – krishnan 2013-02-24 05:46:39