【发布时间】:2013-04-06 16:01:01
【问题描述】:
假设我们在核心数据模型中有两个实体:部门和员工。
部门与员工是一对多的关系。
我有以下 ManagedObjectContexts:
- 根:连接到持久存储协调器
- 主要:与父根的上下文
当我想创建员工时,我会执行以下操作:
- 我在主要上下文中有一个部门
- 我在主上下文中创建了一个员工
- 我将部门分配给员工的部门属性
- 我保存主上下文
- 我保存了根上下文
这会在 Main 上下文和 Root 上下文中创建一个保留循环。
如果我在没有子上下文的情况下执行此操作(全部在 Root 上下文中),那么我可以通过在 Employee 上调用 refreshObject:mergeChanges 来打破保留循环。在我使用这两个上下文的情况下,我仍然可以使用该方法来打破 Main 上下文的循环,但我将如何打破 Root 上下文的循环?
旁注:这是一个描述我的问题的简单示例。在 Instruments 中,我可以清楚地看到分配的数量在增长。在我的应用程序中,我的上下文比一层更深,导致了更大的问题,因为我得到了一个新的实体分配,每个上下文都有保留周期。
15/04 更新:NSPrivateQueueConcurrencyType 与 NSMainQueueConcurrencyType
保存两个上下文后,我可以使用 Department 对象在 Main 上下文中执行 refreshObject:mergeChanges。正如预期的那样,这将重新故障部门对象,打破保留周期并在该上下文中取消分配部门和员工实体。
下一步是打破根上下文中存在的保留循环(保存主上下文已将实体传播到根上下文)。我可以在这里执行相同的技巧,并在带有 Department 对象的 Root 上下文中使用 refreshObject:mergeChanges。
奇怪的是:当我的 Root 上下文是使用 NSMainQueueConcurrencyType 创建的(所有分配都重新出错并解除分配)时,这可以正常工作,但是当我的 Root 上下文是使用 NSPrivateQueueConcurrencyType 创建时不起作用(所有分配都重新出错,但没有释放)。
旁注:Root 上下文的所有操作都在 performBlock(AndWait) 调用中完成
15/04 更新:第 2 部分
当我使用 NSPrivateQueueConcurrencyType 在根上下文上执行另一个(无用,因为没有更改)保存或回滚时,对象似乎已被释放。我不明白为什么这与 NSMainQueueConcurrencyType 的行为不同。
16/04 更新:演示项目
我创建了一个演示项目:http://codegazer.com/code/CoreDataTest.zip
21/04 更新:到达那里
感谢乔迪·哈金斯的帮助!
我正在尝试将 refreshObject:mergeChanges 从我的 ManagedObject didSave 方法中移出。
你能解释一下两者之间的区别吗:
[rootContext performBlock:^{
[rootContext save:nil];
for (NSManagedObject *mo in rootContext.registeredObjects)
[rootContext refreshObject:mo mergeChanges:NO];
}];
和
[rootContext performBlock:^{
[rootContext save:nil];
[rootContext performBlock:^{
for (NSManagedObject *mo in rootContext.registeredObjects)
[rootContext refreshObject:mo mergeChanges:NO];
}];
}];
顶部的不会释放对象,底部的会。
【问题讨论】:
-
有趣的问题。当您将 Department 实体分配给 Employee 的部门属性时,它在哪个上下文中?
-
部门在主要上下文中
-
你有一个小的代码测试用例来证明这一点吗?你如何保存根上下文?另外,当你转储注册对象时你会看到什么?请记住,
performBlock包含一个完整的“用户事件”,但performBlockAndWait没有。 -
@JodyHagins 我添加了一个演示项目来说明一些问题。
标签: ios5 core-data fault retain-cycle