我尝试了这里描述的相同问题。问题是使用 DEFAULT 上下文的子 MOC 保存在 coredata 中,90% 的时间,主线程上下文中的结果会随着来自子 MOC 的更改而更新,但有时它们不会。
在我的测试中,我重复编写相同的实体(不是太快,使用 UI):一个广告实体(最喜爱的计数)以及广告和用户之间的最喜欢的关系。
从 DEFAULT Context 的子 MOC 保存时,这是 MagicalRecord 的预期输出(我也打印了 updatedObjects 计数):
[__52-[ZCServer postFavoriteAd:withDelegate:andSelector:]_block_invoke_2]↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ POST FAVORITE ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
2013-09-19 11:40:35.154 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb8b55e0) → Saving <NSManagedObjectContext (0xb8b55e0): *** UNNAMED ***> on *** BACKGROUND THREAD ***
2013-09-19 11:40:35.155 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb8b55e0) → Save Parents? 1
2013-09-19 11:40:35.155 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb8b55e0) → Save Synchronously? 1
2013-09-19 11:40:35.155 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb8b55e0) → Updated objects = 4
2013-09-19 11:40:35.183 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xba72700) → Saving <NSManagedObjectContext (0xba72700): *** DEFAULT ***> on *** BACKGROUND THREAD ***
2013-09-19 11:40:35.184 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xba72700) → Save Parents? 1
2013-09-19 11:40:35.184 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xba72700) → Save Synchronously? 1
2013-09-19 11:40:35.185 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xba72700) → Updated objects = 2
2013-09-19 11:40:35.188 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3f7740) → Saving <NSManagedObjectContext (0xa3f7740): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD ***
2013-09-19 11:40:35.189 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3f7740) → Save Parents? 1
2013-09-19 11:40:35.189 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3f7740) → Save Synchronously? 1
2013-09-19 11:40:35.189 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3f7740) → Updated objects = 2
2013-09-19 11:40:35.191 __70-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:]_block_invoke29(0xa3f7740) → Finished saving: <NSManagedObjectContext (0xa3f7740): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD ***
[__52-[ZCServer postFavoriteAd:withDelegate:andSelector:]_block_invoke672] ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ------*------ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
**注意:子 MOC 注册了 4 次更新,但在这种情况下,有两个对象(图像元数据)更新了相同的信息。
但有时这是获得的输出(父母没有更新的对象):
[__52-[ZCServer postFavoriteAd:withDelegate:andSelector:]_block_invoke_2]↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ POST FAVORITE ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
2013-09-19 11:37:39.718 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb876d20) → Saving <NSManagedObjectContext (0xb876d20): *** UNNAMED ***> on *** BACKGROUND THREAD ***
2013-09-19 11:37:39.718 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb876d20) → Save Parents? 1
2013-09-19 11:37:39.719 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb876d20) → Save Synchronously? 1
2013-09-19 11:37:39.719 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb876d20) → Updated objects = 4
2013-09-19 11:37:39.720 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xba72700) → Saving <NSManagedObjectContext (0xba72700): *** DEFAULT ***> on *** BACKGROUND THREAD ***
2013-09-19 11:37:39.720 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xba72700) → Save Parents? 1
2013-09-19 11:37:39.720 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xba72700) → Save Synchronously? 1
2013-09-19 11:37:39.721 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xba72700) → Updated objects = 0
2013-09-19 11:37:39.722 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3f7740) → Saving <NSManagedObjectContext (0xa3f7740): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD ***
2013-09-19 11:37:39.723 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3f7740) → Save Parents? 1
2013-09-19 11:37:39.723 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3f7740) → Save Synchronously? 1
2013-09-19 11:37:39.723 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3f7740) → Updated objects = 0
2013-09-19 11:37:39.725 __70-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:]_block_invoke29(0xa3f7740) → Finished saving: <NSManagedObjectContext (0xa3f7740): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD ***
[__52-[ZCServer postFavoriteAd:withDelegate:andSelector:]_block_invoke672] ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ------*------ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
我使用串行队列对 CoreData 执行所有写操作。这个串行队列为当前线程创建一个子 MOC。这是作者的代码:
+ (void) saveWithBlock: (void(^)(NSManagedObjectContext *threadContext))block
{
[ZCMagicalRecord saveWithBlock:block completion:nil];
}
+ (void) saveWithBlock: (void(^)(NSManagedObjectContext *threadContext))block completion:(MRSaveCompletionHandler)completion;
{
dispatch_async( _queue, ^{
NSManagedObjectContext *ctx = [NSManagedObjectContext MR_contextForCurrentThread];
[ctx performBlockAndWait:^{
block( ctx );
[ctx MR_saveWithOptions:MRSaveParentContexts|MRSaveSynchronously completion:completion];
}];
});
}
另一方面,当我使用
[MagicalRecord saveUsingCurrentThreadContextWithBlock:]
UI MainThread 时,更改总是填充到 ROOT 上下文和持久存储中:
[__52-[ZCServer postFavoriteAd:withDelegate:andSelector:]_block_invoke_2]↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ POST FAVORITE ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
2013-09-19 11:47:01.082 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb348550) → Saving <NSManagedObjectContext (0xb348550): *** DEFAULT ***> on *** MAIN THREAD ***
2013-09-19 11:47:01.082 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb348550) → Save Parents? 1
2013-09-19 11:47:01.083 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb348550) → Save Synchronously? 0
2013-09-19 11:47:01.083 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xb348550) → Updated objects = 5
2013-09-19 11:47:01.102 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3cd840) → Saving <NSManagedObjectContext (0xa3cd840): *** BACKGROUND SAVING (ROOT) ***> on *** MAIN THREAD ***
2013-09-19 11:47:01.102 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3cd840) → Save Parents? 1
2013-09-19 11:47:01.103 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3cd840) → Save Synchronously? 0
2013-09-19 11:47:01.103 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0xa3cd840) → Updated objects = 2
2013-09-19 11:47:01.106 __70-[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:]_block_invoke29(0xa3cd840) → Finished saving: <NSManagedObjectContext (0xa3cd840): *** BACKGROUND SAVING (ROOT) ***> on *** BACKGROUND THREAD ***
[__52-[ZCServer postFavoriteAd:withDelegate:andSelector:]_block_invoke676] ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ------*------ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
的代码[MagicalRecord saveUsingCurrentThreadContextWithBlock:]
与我写的类似(我只写它是为了使所有写入顺序):
+ (void) saveUsingCurrentThreadContextWithBlockAndWait:(void (^)(NSManagedObjectContext *localContext))block;
{
NSManagedObjectContext *localContext = [NSManagedObjectContext MR_contextForCurrentThread];
[localContext performBlockAndWait:^{
if (block) {
block(localContext);
}
[localContext MR_saveWithOptions:MRSaveParentContexts|MRSaveSynchronously completion:nil];
}];
}
当我在做这个测试时,CoreData 中没有其他类型的写入。我在这里发布了 POST FAVORITE 示例,但 DELETE FAVORITE 是在帖子之间完成的,并且错误在帖子和删除中随机发生。服务器的响应也已正确验证。
笔记
传递给代码块的对象上下文被忽略。我总是使用[EntityClass MR_CreateEntity]
它使用实际的线程上下文。并且始终使用MR_saveWithOptions:completion:
的上下文是执行块的线程上下文。因此,所有操作都使用相同的上下文。该应用程序非常复杂并且在大多数情况下都可以正常工作,但是这个错误可能会造成比我现在看不到的更多的麻烦。