2016-12-07 1 views
0

Я использую следующий метод, чтобы обновить свой Tableview при создании новых субъектов, используя fetchedResultsController делегат:
Сбой при вставке строки в метод делегата fetchedResultsController (IOS)

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) { 
    switch type { 
    case .insert: 
     //Crash here 
     self.tableView.insertRows(at: [newIndexPath!], with: .automatic) 
    default: 
     print("default") 
    } 
} 

Это работает, но иногда я получение следующей аварии:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. 

The number of rows contained in an existing section after the update (6) must be equal to the number of rows contained in that section before the update (0), plus or minus the number of rows inserted or deleted from that section (1 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out). *** First throw call stack:

Im я, используя fetchedResultsControlle р. Я провел некоторое исследование, и ответы утверждают, что они обновляют numberOfRowsInSection, но у меня есть количество строк в секции, заданных для количества объектов в секции fetchedResultController. Я попытался вызвать reloadData() после & перед insertingRows, но это не исправить. Вот мой метод numberOfRowsInSection:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    if let sections = fetchedResultsController.sections { 
     let currentSection = sections[section] 
     return currentSection.numberOfObjects 
    } 
    return 0 
} 

И мой fetchedResultsController:

lazy var fetchedResultsController: NSFetchedResultsController<Project> = { 

    let userFetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Project") 
    let coreDataStack = CoreDataStack.default() 
    let managedContext = coreDataStack?.managedObjectContext 

    let primarySortDescriptor = NSSortDescriptor(key: "dateCreated", ascending: false) 
    userFetchRequest.sortDescriptors = [primarySortDescriptor] 

     let frc = NSFetchedResultsController(
     fetchRequest: userFetchRequest, 
     managedObjectContext: managedContext!, 
     sectionNameKeyPath: nil, 
     cacheName: nil) 

    frc.delegate = self 

    return frc as! NSFetchedResultsController<Project> 
}() 

// РЕШЕНИЕ:
Это то, что я должен был сделать, чтобы исправить эту проблему, как уже упоминалось Zepar.

func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) { 
    self.tableView.beginUpdates() 
} 

func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) { 
    self.tableView.endUpdates() 
} 

ответ

1

Вы уже забыл сообщить Tableview, что содержание было начато обновление:

[self.tableView beginUpdates]; 

и

[self.tableView endUpdates]; 

Количество измененных разделов и строк должны быть согласованы с извлеченной из них.

Посмотрите в документации, есть пример, а также: https://developer.apple.com/reference/coredata/nsfetchedresultscontrollerdelegate

+0

СПАСИБО! Я обновил свой ответ, чтобы показать решение. Я вытягивал волосы из головы в течение последних 3 часов. –

+0

Вы также должны указать, что вы должны бросить эти методы внутри метода делегата NSFetchedResultsController (controllerWillChangeContent & controllerDidChangeContent). Я попытался поставить beginUpdates и endUpdates до и после (соответственно) self.tableView.insertRows и не был решением. –

+0

Да, именно поэтому я предоставил ссылку на документацию. Хорошо знать, как это работает и как использовать из источника. – zepar

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