2

У меня возникла проблема с получением точных обновлений из NSFetchedResultsControllerDelegate после использования NSBatchDeleteRequest, изменения происходят как тип обновления, а не тип удаления в методе делегирования didChange. Есть ли способ, чтобы изменения вносились как удаление? (У меня разные сценарии для удаления vs update).Использование NSFetchedResultsController w/NSBatchDeleteRequest

Функция удаления запроса: (использует личный контекст предоставленный вызывающему)

fileprivate class func deletePeopleWith(ids: Set<Int>, usingContext context: NSManagedObjectContext) { 

    let fr: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Person") 

    var predicates: [NSPredicate] = [] 
    ids.forEach { 

     predicates.append(NSPredicate(format: "id = %ld", $0)) 
    } 

    fr.predicate = NSCompoundPredicate(orPredicateWithSubpredicates: predicates) 

    let dr = NSBatchDeleteRequest(fetchRequest: fr) 
    dr.affectedStores = context.parent?.persistentStoreCoordinator?.persistentStores 

    do { 

     try context.parent?.execute(dr) 
     context.parent?.refreshAllObjects() 
     print("Deleting person") 

    } catch let error as NSError { 

     let desc = "Could not delete person with batch delete request, with error: \(error.localizedDescription)" 
     debugPrint(desc) 
    } 

} 

Результаты в:

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) { 

    DispatchQueue.main.async { 

     let changeDesc = "Have change with indexPath of: \(indexPath), new index path of: \(newIndexPath) for object: \(anObject)" 
     var changeType = "" 
     switch type { 

     case .delete: 
      changeType = "delete" 

     case .insert: 
      changeType = "insert" 

     case .move: 
      changeType = "move" 

     case .update: 
      changeType = "update" 

     } 

     print(changeDesc) 
     print(changeType) 
    } 

} 

Печать:

Have change with indexPath of: Optional([0, 0]), new index path of: Optional([0, 0]) for object: *my core data object* 
update 
+0

Выполняется удаление в родительском контексте, и вы сказали, что хотите удалить, используя предоставленный личный контекст. – ELKA

+0

@ELKA созданный контролер результатов создается с использованием родительского контекста, родительский контекст также является контекстом, родителем которого является постоянное хранилище, где записи должны быть удалены. –

+0

Таким образом, context.parent будет основным NSManagedObjectContext, который совпадает с контекстом NSFetchedResultController. Верный? – ELKA

ответ

4

От компании Apple documentation:

Пакетное удаление выполняется быстрее, чем удалять объекты Core Data самостоятельно в коде, поскольку они работают в самом постоянном хранилище на уровне SQL. Как часть этой разницы, изменения, действующие в постоянном хранилище, не отражаются в объектах, которые в настоящее время находятся в памяти.

После выполнения пакетного удаления удалите все объекты в памяти, которые были удалены из постоянного хранилища.

См. Раздел Updating Your Application After Execution для обработки объектов, удаленных NSBatchDeleteRequest.

+0

Документы сами по себе не работали, но обновляли тип результата до идентификатора объекта в запросе удаления, а затем вызывали обновление всех объектов в контексте, используемом получателем результатов, получили внесенное изменение как удаление! –

0

Вот образец, работает для меня. Но я не нашел, как обновлять удаление с помощью анимации, потому что NSFetchedResultsControllerDelegate не срабатывал.

@IBAction func didPressDelete(_ sender: UIBarButtonItem) { 
     let managedObjectContext = persistentContainer.viewContext 
     let request = NSFetchRequest<NSFetchRequestResult>(entityName: String(describing: Record.self)) 
     let deleteRequest = NSBatchDeleteRequest(fetchRequest: request) 

     do { 
      // delete on persistance store level 
      try managedObjectContext.execute(deleteRequest) 

      // reload the whole context 
      managedObjectContext.reset() 
      try self.fetchedResultsController.performFetch() 
      tableV.reloadData() 
     } catch { 
      print("") 
     } 
    } 

Thanks.

Смежные вопросы