0

У меня есть два частных контекста 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 

    } 
} 

ответ

1

Рассмотрим изменения конфигурации контекста. Вместо создания дочерних контекстов контекста главной очереди вы можете создать фоновый контекст непосредственно поверх координатора постоянного хранилища. То же самое касается основного контекста. Теперь, когда вы импортируете свои данные и сохраняете их в фоновых контекстах, ваши данные будут записываться на уровень sql через psc. В вашей предыдущей настройке фоновые контексты сохранили бы их родителям, что было основным контекстом. Чтобы распространить изменения из фоновых контекстов на главный, прослушайте уведомление nsmanagedobjectcontextdidsave. Затем вы можете объединить изменения из фонового контекста в основной. Это будет меньше налогов. Зависит, однако, от запроса на выборку. Обязательно попробуйте оптимизировать это как можно больше.

Проверьте документ: https://developer.apple.com/library/ios/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSManagedObjectContext_Class/

Успехов

+0

Мне очень нравится эта идея. Это будет немного, прежде чем я смогу его реализовать. Мне удалось решить мою проблему, изменив назначение делегата контроллера результатов через другие вызовы делегатов, но это звучит чище/быстрее. –