Swift NSFetchedResultsController Сбой при обновлении объекта / раздела - PullRequest
0 голосов
/ 13 июня 2019

Итак, у меня есть FRC в 'resultsTVC', который загружает список элементов CoreData, разбитых на разделы одним из полей CoreData ('label').

Если я выбираю результат для его редактирования, второй «editorTVC» загружается с данными объекта.Однако, если я изменяю поле «label», я получаю ошибку от «resultsTVC».

*** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKitCore_Sim/UIKit-3698.103.12/UITableView.m:2043
[error] fault: Serious application error.  An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:.  Invalid update: invalid number of sections.  The number of sections contained in the table view after the update (4) must be equal to the number of sections contained in the table view before the update (3), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted). with userInfo (null)
CoreData: fault: Serious application error.  An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:.  Invalid update: invalid number of sections.  The number of sections contained in the table view after the update (4) must be equal to the number of sections contained in the table view before the update (3), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted). with userInfo (null)

Вот мой код:

...
let fetchRequest: NSFetchRequest<DrugMethods> = DrugMethods.fetchRequest()
            let predicate = NSPredicate(format: "child = %@", self.parentItem)
            let sortDescriptorSublabel = NSSortDescriptor(key: "sublabel", ascending: true, selector: #selector(NSString.localizedStandardCompare(_:)))

        fetchRequest.predicate = predicate
        fetchRequest.sortDescriptor = sortDescriptorSublabel

        if let appDelegate = (UIApplication.shared.delegate as? AppDelegate) {
            let context = appDelegate.persistentContainer.viewContext
            fetchResultController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: "label", cacheName: nil)

            fetchResultController.delegate = self

            do {
                try fetchResultController.performFetch()
                if let fetchedObjects = fetchResultController.fetchedObjects {
                    methods = fetchedObjects
                }
            } catch {
                print(error)
            }
        }
    }

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

    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
        switch type {
        case .insert:
            if let newIndexPath = newIndexPath {
                tableView.insertRows(at: [newIndexPath], with: .automatic)
            }
        case .delete:
            if let indexPath = indexPath {
                tableView.deleteRows(at: [indexPath], with: .automatic)
            }
        case .update:
            if let indexPath = indexPath {
                tableView.reloadRows(at: [indexPath], with: .automatic)
            }
        default:
            tableView.reloadData()
        }

        if let fetchedObjects = controller.fetchedObjects {
            methods = (fetchedObjects as? [ChildItems])!
        }
    }

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

    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
        switch type {
        case .insert:
            tableView.insertSections(IndexSet(integer: sectionIndex), with: .automatic)
        case .delete:
            tableView.deleteSections(IndexSet(integer: sectionIndex), with: .automatic)
        case .move:
            break
        case .update:
            break
        @unknown default:
            break
        }
    }

    // MARK: - Table view data source
    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        if let sections = fetchResultController.sections {
            let currentSection = sections[section]
            return currentSection.name
        }
        return nil
    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        if let sections = fetchResultController.sections {
            return sections.count
        }
        return 0
    }

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

        return 0
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        ...
    }



    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "showMethodEditor" {
            // Load for editing
            // Get selected Method
            let data = fetchResultController.object(at: tableView.indexPathForSelectedRow!)

            let destinationController = segue.destination as! ProtocolEditorTableViewController
            destinationController.data = data
        }

    }


    // Table Row Selection
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        performSegue(withIdentifier: "showMethodEditor", sender: self)
        tableView.deselectRow(at: indexPath, animated: true)
    }

}

Я смотрел различные решения онлайн, но ничего не работает

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