Swiftpack.co - hibernat/DiffableWithReload as Swift Package

Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
hibernat/DiffableWithReload
Automated reloadItems for diffable datasources
.package(url: "https://github.com/hibernat/DiffableWithReload.git", from: "1.0.3")

DiffableWithReload

Automated call of reloadItems(_:) for diffable datasources

The new (iOS 13+) diffable datasources are great step forward making UITableView and UICollectionView much easier to use. Except one operation: item reloads.

Why

Modern app architectures store data in some kind of ViewModel or ViewStore (The Composable Architecture, CombineFeedback, and many others), while the UI just observes the data.

Very likely, the ViewModel/ViewStore:

  • stores data that should be displayed in table/collection view, often transformed or enriched (this data is usually private to the ViewModel/ViewStore)
  • there is an array of section identifiers
  • and a dictionary of item identifiers (section identifier is the key)

Thanks to the diffable datasources UITableViewDiffableDataSource and UICollectionViewDiffableDataSource, animated updating the table/collection view is very easy:

The only troubled step is the last one: Which items have to be reloaded?

DiffableWithReload automates identification of items that require reload, so you do not need to care about reloading. Cells needing reload (and only these) are automatically reloaded (when snapshot is applied).

Classes

DiffableWithReload subclasses UITableViewDiffableDataSource and UICollectionViewDiffableDataSource (still as generic classes) so you can use them with your data types.

For basic use, there are available:

TableViewDiffableReloadingDataSource<SectionIdentifierType: Hashable, ItemIdentifierType: Hashable, EquatableCellContent: Equatable>

CollectionViewDiffableReloadingDataSource<SectionIdentifierType: Hashable, ItemIdentifierType: Hashable, EquatableCellContent: Equatable>

For advanced use, when you need (for example) data locking, there are available these subclasses:

TableViewDiffableDelegatingDataSource<SectionIdentifierType: Hashable, ItemIdentifierType: Hashable, Delegate: ReloadingDataSourceDelegate, EquatableCellContent: Equatable>

CollectionViewDiffableDelegatingDataSource<SectionIdentifierType: Hashable, ItemIdentifierType: Hashable, Delegate: ReloadingDataSourceDelegate, EquatableCellContent: Equatable>

Examples

// change data in the cars array
cars.changeColorOfAllCars(brand: .volkswagen)
// apply the current snapshot
let snapshot = diffableDataSource.snapshot()
// items for reload are automatically created
diffableDataSource.applyWithItemsReloadIfNeeded(snapshot, animatingDifferences: true)

It is highly recommended to review the example code. There are 3 tabs in the example iOS application:

  • First tab (Cars): Elementary example where you can see on 100 lines of code, how it works
  • Second tab (Cars and Motorcycles): Close to real-world example, with view model and Combine used for observing the changes.
  • Third tab (Motorcycles): Demonstrating use with collection view and more cell reuse identifiers.

Under the hood (How it works)

  • for each cell used in the table/collection view is stored the displayed content
  • displayed content is generic type EquatableCellContent (conforming to Equatable)
  • when snapshot is being applied, the currently displayed cell content is compared to the current data source content, and if these are not equal, cell will be reloaded
  • DiffableWithReload temporarily stores the displayed cell content (EquatableCellContent) for each used cell in the table/collection view. Again, it can be any type conforming to Equatable, but there are two handy structs creating equatable content:
  • EncodableContent creating Data? value from the specified properties: Data? is unique identifier of the displayed content and can be easily created from any Encodable property of your underlaying data. The provided data value is an Optional, because encode(to:) may throw. In such a case the cell is always reloaded.
  • HashableContent creating Int (the hash) value from the specified properties: hashValue is not so unique identifier of the displayed content, however, may be good enough. Default choice should be EncodableContent.

Setup Instructions

CocoaPods

To integrate Toast-Swift into your Xcode project using CocoaPods, specify it in your Podfile:

pod 'DiffableWithReload', '~> 1.0.0'

and in your code use import DiffableWithReload.

Swift Package Manager

When using Xcode 11 or later, you can install DiffableWithReload by going to your Project settings > Swift Packages and add the repository by providing the GitHub URL. Alternatively, you can go to File > Swift Packages > Add Package Dependencies...

Compatibility

  • Version 1.0.0 requires Swift 5
  • Example project uses multiple trailing closures and requires Swift 5.3

GitHub

link
Stars: 2
Last commit: 4 weeks ago

Ad: Job Offers

iOS Software Engineer @ Perry Street Software
Perry Street Software is Jack’d and SCRUFF. We are two of the world’s largest gay, bi, trans and queer social dating apps on iOS and Android. Our brands reach more than 20 million members worldwide so members can connect, meet and express themselves on a platform that prioritizes privacy and security. We invest heavily into SwiftUI and using Swift Packages to modularize the codebase.

Submit a free job ad (while I'm testing this). The analytics numbers for this website are here.

Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics