Applying NSDiffableDataSourceSnapshot to UITableViewDiffableDataSource cause 'NSInternalInconsistencyException'

I am trying to implement a UITableViewViewDiffableDataSource for my tableview. My code compiles fine, however I keep running into this error the first time I apply a snapshot to it, with the following error:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: section < [_state.dataSourceSnapshot numberOfSections]'

Here is my code:

BaseDisplayManager

class BaseDisplayManager: NSObject, UITableViewDelegate, BaseDiffableDataSourceDelegate {
   var tableData = [[BaseViewModelProtocol]]()
   var sections: [DiffableSection] = []
...

   func setupDiffableDataSource(forTableView tableView: UITableView) {
      dataSource = BaseDiffableDataSource(tableView: tableView, cellProvider: { (tableView, indexPath, model) -> UITableViewCell? in
          guard let model = model as? BaseViewModelProtocol else { return nil }
          let cell = tableView.dequeueReusableCell(withIdentifier: model.cellIdentifier, for: indexPath)
          (cell as? TableViewCell)?.model = model
          (cell as? NoSwipeTableViewCell)?.model = model
          return cell
      })

      dataSource.delegate = self
   }

   func reloadSnapshot() {
      var snapshot = NSDiffableDataSourceSnapshot<AnyHashable, AnyHashable>()
      snapshot.appendSections(sections.map { $0.sectionIdentifier() })
      sections.forEach { [weak self] section in
          guard let items = self?.tableData[section.sectionIndex()] as? [AnyHashable] else { return }
          snapshot.appendItems(items, toSection: section.sectionIdentifier())
      }
    
      dataSource.apply(snapshot, animatingDifferences: true)
   }

DiffableSection

protocol DiffableSection {
  func sectionIndex() -> Int
  func sectionIdentifier() -> AnyHashable
}

BaseDiffableDataSource

protocol BaseDiffableDataSourceDelegate: class {
   func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool
   func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath)
   func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool
   func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath)
}

class BaseDiffableDataSource: UITableViewDiffableDataSource<AnyHashable, AnyHashable> {

   weak var delegate: BaseDiffableDataSourceDelegate! = nil

   override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    return delegate.tableView(tableView, canEditRowAt: indexPath)
   }

   override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
    return delegate.tableView(tableView, commit: editingStyle, forRowAt: indexPath)
   }

   override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
    return delegate.tableView(tableView, canMoveRowAt: indexPath)
   }

   override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
    return delegate.tableView(tableView, moveRowAt: sourceIndexPath, to: destinationIndexPath)
   }
}

}

Upvotes: 0

Views: 432

Answers (1)

Jordan
Jordan

Reputation: 31

I ran into the same issue in a ViewController which was a subclass of UITableViewController.

For me it was that I was configuring my datasource and applying a snapshot in viewWillAppear() AND calling super.viewWillAppear() before. Removing the super call did the trick.

Upvotes: 2

Related Questions