UITableViewDiffableDataSouce: недопустимое обновление: недопустимое количество разделов
Я пытаюсь применить пустой снимок, это приводит к сбою моего приложения. Я пытаюсь отладить его уже 2 дня и, похоже, не могу найти способ решить эту проблему. Ниже приведен код, который я запускаю:
//
// ItemsListDiffableVC.swift
// FetchRewardsCodingExercise
//
// Created by Vandan Patel on 11/26/20.
//
import UIKit
final class ItemsListDiffableVC: UIViewController {
private var tableView: UITableView!
private var dataSource: ItemDataSource!
private var groupedItems = [Dictionary<Int, [Item]>.Element]()
var presenter: ItemsListPresentable!
private let cellReusableID = "itemCell"
override func viewDidLoad() {
super.viewDidLoad()
configureTableView()
presenter.didLoadView()
}
private func configureTableView() {
tableView = UITableView()
tableView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
tableView.backgroundColor = .systemGroupedBackground
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellReusableID)
view.addSubview(tableView)
}
private func configureDataSource() {
dataSource = ItemDataSource(tableView: self.tableView, cellProvider: { (tableView, indexPath, item) -> UITableViewCell? in
let cell = tableView.dequeueReusableCell(withIdentifier: self.cellReusableID, for: indexPath) as! ItemCell
cell.configureCell(withTitle: item.name ?? "")
return cell
})
}
}
extension ItemsListDiffableVC: ItemsListViewable {
func display(groupedItems: [Dictionary<Int, [Item]>.Element]) {
DispatchQueue.main.async {
self.configureDataSource()
self.update(with: groupedItems)
}
}
func display(error: String) {
}
}
extension ItemsListDiffableVC {
private func update(with groupedItems: [Dictionary<Int, [Item]>.Element]) {
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
dataSource.apply(snapshot, animatingDifferences: true, completion: nil)
}
}
class Section: Hashable {
let sectionName: String
let identifier = UUID()
init(sectionName: String) {
self.sectionName = sectionName
}
func hash(into hasher: inout Hasher) {
hasher.combine(identifier)
}
static func == (lhs: Section, rhs: Section) -> Bool {
return lhs.identifier == rhs.identifier
}
}
class ItemDataSource: UITableViewDiffableDataSource<Section, Item> {
var groupedItems = [Dictionary<Int, [Item]>.Element]()
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return groupedItems[section].key.sectionTitle
}
}
struct Item: Codable, Hashable {
let id: Int
let listId: Int
let name: String?
}
Я получаю вот такую ошибку:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of sections. The number of sections contained in the table view after the update (0) must be equal to the number of sections contained in the table view before the update (1), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted).'
Я не понимаю, почему еще до обновления есть один раздел и как с ним обращаться.
Благодарю.
4 ответа
У меня была та же проблема, что и я, поворачивая
animatingDifferences
на ложь, и авария исчезла
Прежде всего, UIDiffableDataSource не предназначен для ссылочного типа, поэтому я предлагаю преобразовать все классы вашей модели в структуру.
Я подозреваю, что проблема заключается в коде, который вы нам не показали (поскольку код явно неполный; вы не объявляете Item, и, похоже, у вас нигде нет данных). Однако вот некоторые мысли о коде, который вы показали:
Это не имеет никакого смысла:
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
dataSource.apply(snapshot, animatingDifferences: true, completion: nil)
Этот снимок пуст. Таким образом, нет данных для обновления и применения различий. Ваша функция названа
func update(with groupedItems:
но на самом деле несмотря ни на что
groupedItems
могут быть переданы вам, вы просто выбрасываете их и используете этот пустой снимок.
Кроме того, после первоначального заполнения источника данных, которое происходит всего один раз, вы больше никогда не создадите моментальный снимок. Вы всегда получаете каждый последующий снимок из источника данных, изменяете его и применяете.
Кроме того, это показывает неправильное представление о том, что такое источник данных для различий:
class ItemDataSource: UITableViewDiffableDataSource<Section, Item> {
var groupedItems = [Dictionary<Int, [Item]>.Element]()
}
Вы не используете отдельную переменную экземпляра для хранения данных в различном источнике данных. Сам источник данных diffable содержит данные, которые передаются ему моментальным снимком, когда он применяется.
По сути, вам нужно решить, где находится источник истины для этих данных, и последовательно заполнить источник данных табличного представления оттуда. Обычное дело в том, что diffable источник данных сам по себе является источником истины; Если у вас есть веская причина использовать "резервное хранилище", прекрасно (возможно, ваши данные обновляются асинхронно из сети?), но тогда не используйте два из них.
tableView.dataSource = dataSource
Я не вижу этого нигде в представленном коде.