CoreData - неверное количество строк при использовании извлеченного контроллера - PullRequest
1 голос
/ 22 января 2020

Я знаю, что это распространенная ошибка, но я не понимаю, почему это происходит здесь. В первом v c, когда нажимается кнопка добавления, пользователь переключается на второй v c, чтобы создать новую запись. Во втором v c все идет хорошо, пока я не пытаюсь сохранить контекст. В этот момент первый v c пытается вставить новую запись, и приложение вылетает без сохранения.

Второй V C:

private func createNewRecord() {
   let newRecord = Record(context: context)
   newRecord.recordNumber = "xxxx"
   currentCustomer?.addToRecords(newRecord)
   coreData?.saveContext() //App tries to insert new record on first VC here and crashes
   fetchCurrentRecord()
} 

Первый V C:

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
   switch type {
   case .insert:
      if let insertIndexPath = newIndexPath {
         recordTableView.insertRows(at: [insertIndexPath], with: .fade) //CRASH!!
      }
etc.

методы tableView (первый V C):

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
   return recordFetchedController.fetchedObjects?.count ?? 0
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
   let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! RecordCell
   let record = recordFetchedController.fetchedObjects![indexPath.row] as Record
   cell.recordNumber.text = record.recordNumber
   return cell
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
   performSegue(withIdentifier: "EditRecordSegue", sender: self)
   tableView.deselectRow(at: indexPath, animated: true)
}

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
   if editingStyle == .delete {
      let record = recordFetchedController.fetchedObjects![indexPath.row] as Record
   context.delete(record)
   coreData?.saveContext()
   }
}

FetchedResultsController:

func configureFetchedController(searchString: String) {
   let customerFetchRequest = NSFetchRequest<Record>(entityName: "Record")

   let predicate = NSPredicate(format: "customer.name CONTAINS[c] %@", searchString)
   customerFetchRequest.predicate = predicate

   let firstSortDescriptor = NSSortDescriptor(key: "dateModified", ascending: false)
   customerFetchRequest.sortDescriptors = [firstSortDescriptor]

   recordFetchedController = NSFetchedResultsController<Record>(
   fetchRequest: customerFetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)  

   recordFetchedController.delegate = self
}

И вот ошибка: количество строк, содержащихся в существующем разделе после обновления (1), должно быть равно количеству строк, содержащихся в этом разделе до обновление (1), плюс или минус количество строк, вставленных или удаленных из этого раздела (1 вставлено, 0 удалено) и плюс или минус количество строк, перемещенных в или из этого раздела (0 перемещено, 0 перемещено) , с userInfo (ноль)

Ответы [ 2 ]

1 голос
/ 11 февраля 2020

Одна из причин этой ужасной проблемы!

Короче говоря, у меня был базовый класс для табличного представления, о котором я забыл. Как это случилось, у него была перегрузка для reloadData ...

override func reloadData() {
    super.reloadData()

    if isLoading {
        emptee.removeFromSuperview()
        return
    }

    if dataSource?.tableView(self, numberOfRowsInSection: 0) == 0 {
        addSubview(emptee)
    }
    else {
        emptee.removeFromSuperview()
    }
}

Как вы можете видеть, это просто относится к "пустому сообщению"

В коде это делает звонок для numberOfRowsInSection ...

К сожалению, у меня был звонок вот так:

override func reloadData() {
    // my code ...
    super.reloadData()
}

, а не вот так!

override func reloadData() {
    super.reloadData()
    // my code ...
}

Это был весь проблема.

1 голос
/ 23 января 2020

Проблема оказалась совершенно не связанной с моим извлеченным кодом контроллера. Существует отдельная таблица клиентов, которая отправляет уведомление при выборе нового клиента. Второй V C отвечает на это уведомление, возвращаясь к первому V C. Что было хорошо. Но позже я решил, что таблица клиентов должна перемещать текущего выбранного клиента на вершину при добавлении новой записи. Это имело непреднамеренное последствие отправки другого уведомления, что привело к тому, что второй V C начал создавать новую запись, но затем был немедленно отклонен. И кра sh. Это заставляет меня думать, что мне нужно больше узнать о тестировании.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...