Diffable uitableview


Diffable table

Research

Keep your identifiers simple and to the point

When you choose your identifiers for your diffable data source and snapshot, try to make sure they only include data that will be rendered or influences the rendering. When I was stuck with reloading my cells, I was using NSManaged object subclasses to drive my data source. This seems to work well enough because everything was there. Items were added, removed and reordered. However, for some reason, my data source never seemed to pick up changes to the properties of my managed objects. I eventually got around this by providing a struct that contained the data I wanted to render rather than the entire managed object. A nice way I’ve found to define these structs is as extensions on the models themselves:

extension MyModel {
  struct Diffable {
    let id: UUID
    let title: String
    let subtitle: String
    // other properties that will be rendered on the cell
    init(model: MyModel) {
      self.id = model.id
      self.title = model.title
      self.subtitle = model.subtitle
    }
  }
}

Always create typealiases of datasources:

fileprivate typealias UserDataSource     = UICollectionViewDiffableDataSource<ViewController.Section, Contact>
fileprivate typealias DataSourceSnapshot = NSDiffableDataSourceSnapshot<ViewController.Section, Contact>

When using this approach, you’d replace the MyModel item identifier with MyModel.Diffable, and when you create your snapshot, you must convert all MyModel instances to MyModel.Diffable. Since the initializer for the MyModel.Diffable object takes an instance of MyModel this is fairly straightforward:

Hide in-activce sections:

Gotchas:

  • instead of storing data in an array, use a currentSnapshot variable as the one source of truth

Resources

Todo: