在后台线程中加载 CoreData
Posted
技术标签:
【中文标题】在后台线程中加载 CoreData【英文标题】:Loading CoreData in a background thread 【发布时间】:2012-05-18 21:12:48 【问题描述】:我觉得我今天已经阅读了 Stack Overflow 上的所有 CoreData 问题,但仍然非常卡住。 :)
我正在开发一个使用 CoreData 的应用程序,该应用程序基于斯坦福大学 cs193p 第 14 讲(Photomania 应用程序)中说明的方法。它使用实现 NSFetchedResultsController 委托的 UITableViewController 子类,当然,在获取结果时表格会自动更新。
一切正常,但当 Document 填充数据时 UI 会阻塞,因为它发生在主线程(即文档的 managedObjectContext)中。我已经在后台线程中下载数据,这只是实际填充导致阻塞的 NSManagedObjects 的代码。该讲座提到使用 NSManagedObjectContext 的 Parent 上下文来在后台加载 Document,然后在主线程中“重新获取”数据以填充表格。我几乎可以正常工作(我认为),除了我的表格经常出现重复条目。似乎 [self.tableView beginUpdates] / [self.tableView endUpdates] 会解决这种问题,但是因为我正在后台上下文中保存 NSManagedObjectContext 我不知道我会把它放在哪里。
我也可能以完全错误的方式解决这个问题。 :) 无论如何,这里是相关代码:
NSManagedObjectContext *backgroundContext;
backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
// document is my UIManagedDocument
backgroundContext.parentContext = document.managedObjectContext;
[backgroundContext performBlockAndWait:^
// Do stuff here to populate the document.
[backgroundContext save:nil];
];
【问题讨论】:
【参考方案1】:它仍在等待,因为您告诉它这样做。使用 performBlock,这样它就可以在自己的线程上工作。
[backgroundContext preformBlock:^
// Do your background stuff
[backgroundContext save:&error]; // handle the error
[document.managedObjectContext performBlock:^
// Tell the document it has dirty data and should save
[document updateChangeCount:UIDocumentChangeDone];
// Do any UI-related stuff
];
];
当更改被推送到主上下文时,获取的结果控制器将自动更新。
【讨论】:
【参考方案2】:从您的代码中,我看不出问题的真正所在。你没有很清楚你正在加载的“文档”是什么。无论如何,什么可能对您有所帮助:尝试在后台线程(您拥有的)中进行整个加载,发布通知以让表视图控制器了解更新,然后向控制器发送消息,例如:
[self.tableView reloadData];
那么你就不需要beginUpdates
也不需要endUpdates
,但是如果你找到了你需要使用它们的方法(通常NSFetchedResultsController
的委托方法在-(void)controllerWillChangeContent:(NSFetchedResultsController *)controller
和- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
中使用它),那么在更新数据之前和之后发送这些消息。
希望能有所帮助……
【讨论】:
顺便说一下,据我所知,NSFetchedResultsController 会监听来自 Core Data 的通知,但不确定是否来自每个… 谢谢,但在尝试了您和 Jody 的建议并没有发现任何变化后,我决定检查文档,结果当我在屏幕上看到重复条目时,文档中确实存在重复条目。所以这是一个核心数据问题,而不仅仅是一个 UI 故障。 这几乎就像 [backgroundContext save] 有时会添加到父上下文中的 Document 而不是出于某种原因替换它。保存从不报告错误。该文档是我之前在控制器中创建的 UIManagedDocument。【参考方案3】:嗯,不知道为什么,但这解决了我的问题:https://***.com/a/9451450/314051。具体来说,就在 [backgroundContext 保存] 之前:
NSSet *inserts = [backgroundContext insertedObjects];
[backgroundContext obtainPermanentIDsForObjects:[inserts allObjects] error:&error];
我需要做一些研究才能确切了解原因。感谢您的建议,这些建议帮助我确定这不是 UI 问题。
【讨论】:
以上是关于在后台线程中加载 CoreData的主要内容,如果未能解决你的问题,请参考以下文章
Core Data,在后台线程中修改 NSManagedObject
在 cellForRowAtIndexPath 中获取 iOS CoreData 后台线程