У меня есть два частных контекста NSManagedObject, которые асинхронно обрабатывают объект Core Data в фоновом потоке, после того как эти контексты обновляются, они сохраняются в основном контексте основного потока. В этот момент, если было много обновлений, мой основной контекст и NSFetchedResultsController захлопнулись с обновлениями. Есть ли способ сделать это в партии?Получите пакетное обновление для 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
}
}
Мне очень нравится эта идея. Это будет немного, прежде чем я смогу его реализовать. Мне удалось решить мою проблему, изменив назначение делегата контроллера результатов через другие вызовы делегатов, но это звучит чище/быстрее. –