我有两个私有NSManagedObject上下文,用于处理在后台线程上异步更新Core Data实体,在更新这些上下文后,它们保存到主线程的主上下文中。那时,如果有很多更新,我的主要上下文和NSFetchedResultsController会受到更新的攻击。有没有办法批量执行此操作?
我尝试发送通知,使用委托等,其中数据在子上下文中更新,并且它们按预期工作,但在主要上下文保存操作发生之前都会在后台线程上触发。
我认为理想情况下,我希望在“大”保存正在进行时分离代理,在完成时以某种方式得到通知,执行异步提取请求并在请求完成时在表上调用reloadData。
我有一个UITableView和一个NSFetchedResultsController使用UIViewController上的主上下文:
let fetchRequest = NSFetchRequest(entityName: Message)
fetchRequest.predicate = NSPredicate(format: "groupId == %@", self.groupId)
let idSort = NSSortDescriptor(key: "id", ascending: true)
fetchRequest.sortDescriptors = [idSort]
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.coreDataStack.context, sectionNameKeyPath: nil, cacheName: nil)
do {
try self.fetchedResultsController.performFetch()
} catch {
print("error fetch")
}
self.fetchedResultsController.delegate = self
然后我使用NSFetchedResultsController提供的委托:
func controllerWillChangeContent(controller: NSFetchedResultsController) {
dispatch_async(dispatch_get_main_queue()) { () -> Void in
self.tableView?.beginUpdates()
}
}
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
dispatch_async(dispatch_get_main_queue()) { () -> Void in
switch type {
case .Insert:
self.tableView?.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Automatic)
self.newIndexPath = newIndexPath
case .Delete:
self.tableView?.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Automatic)
case .Update:
return
case .Move:
self.tableView?.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Automatic)
self.tableView?.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Automatic)
}
}
}
func controllerDidChangeContent(controller: NSFetchedResultsController) {
dispatch_async(dispatch_get_main_queue()) { () -> Void in
self.tableView?.endUpdates()
// Scroll the table view
if self.newIndexPath != nil {
self.messagesTable?.scrollToRowAtIndexPath(self.newIndexPath!, atScrollPosition: .Bottom, animated: false)
self.newIndexPath = nil
}
}
}
func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
let indexSet = NSIndexSet(index: sectionIndex)
switch type {
case .Insert:
self.tableView!.insertSections(indexSet, withRowAnimation: .Automatic)
case .Delete:
self.tableView!.deleteSections(indexSet, withRowAnimation: .Automatic)
default:
break
}
}
答案 0 :(得分:1)
考虑更改您的上下文配置。您可以直接在持久性存储协调器之上创建背景上下文,而不是创建主队列上下文的子上下文。主要背景也是如此。 现在,当您导入数据并保存在后台上下文中时,您的数据将通过psc写入sql层。在之前的设置中,后台上下文将保存到其父级,这是主要上下文。 为了将更改从后台上下文传播到main,请侦听nsmanagedobjectcontextdidsave通知。然后,您可以将背景上下文中的更改合并到main中。这将减少税收。然而,取决于获取请求。务必尽可能地优化这一点。
祝你好运