我正在处理一个场景,其中存在一些对象,如果要删除它们,则会通过级联删除关系导致指数级的删除。这样,删除这些对象中的20个可能最终导致约3,000个对象被删除。如果与主上下文一起执行,这可能导致保存速度非常慢。
为了解决这个问题,我创建了一个'worker'上下文,该上下文使用与主上下文相同的持久存储,在那里进行更改,然后保存worker上下文并将这些更改与主上下文合并:
NSManagedObjectContext *workerContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
workerContext.persistentStoreCoordinator = mainContext.persistentStoreCoordinator;
[notificationCenter addObserver:self selector:@selector(workerContextDidSave:) name:NSManagedObjectContextDidSaveNotification object:workerContext];
// Here I do a 'superficial' deletion on the main context, so the UI updates,
// but do the actual deletion on the worker context. Then I save the worker context:
[workerContext save:nil];
// Which fires spawnedWorkerContextDidSave:, where I merge changes to the main context:
[mainContext performBlockAndWait:^{
[mainContext mergeChangesFromContextDidSaveNotification:notification];
}];
我的问题是:处理这类大型删除批次的最常用方法是什么?我上面的方法有什么陷阱吗?此外,合并会在主线程上引起一些小的延迟,但是与删除和保存在主线程上时的位置相比,没有什么变化。
最佳答案
通过第二上下文删除数据的方法很好。
如果您首先预取数据,则可能会发现它的工作速度更快:只需对要在后台上下文中删除的对象执行获取请求,并将关系设置为预取。删除之前,这会将数据拉到行缓存(内存)中,这样可以将旅行保存到磁盘。
如果发现合并主线程中的更改存在延迟,可以考虑仅重置主上下文。缺点是您的应用必须重新获取其所有数据。例如,您可能会发出火灾通知,以警告应用程序的不同部分:a)即将发生重置,b)发生了重置。
最后,Core Data中现在有API,可以在后台执行大型删除操作而无需将数据拉入内存。主要缺点是您必须小心自己合并已删除的对象,因为上下文不会知道它们已被删除。