Skip to content

Repository files navigation

FHDiffableViewControllers

Xcode BuildVersionLicenseTweet

UITableViewController and UICollectionViewController based on a DiffableDataSource.

Requirements

  • macOS 10.15+ (Catalyst)
  • iOS 13.0+
  • tvOS 13.0+

Installation

Add the following to the dependencies of your Package.swift:

.package(url:"https://github.com/FelixHerrmann/FHDiffableViewControllers.git", from:"x.x.x")

Xcode

Add the package to your project as shown here.

Manual

Download the files in the Sources folder and drag them into you project.

Usage

If you are using Swift Package Manager, you have to import FHDiffableViewControllers to your file with import FHDiffableViewControllers.

Now you can inherit your view controller class from FHDiffableTableViewController and FHDiffableCollectionViewController.


But first you need a SectionIdentifier and ItemIdentifier which will be used for the generic types. Both types have to conform to Hashable.

enumSection{case main, detail
}structItem:Hashable{vartitle:String}

It is recommend to conform the item to Identifiable because the app crashes if there are duplicates in the data source!


These classes can be subclassed like that:

classTableViewController:FHDiffableTableViewController<Section,Item>{overridevarcellProvider:UITableViewDiffableDataSource<Section,Item>.CellProvider{return{ tableView, indexPath, item inletcell= tableView.dequeueReusableCell(withIdentifier:"cell", for: indexPath)
cell.textLabel?.text = item.title
return cell
}}overridefunc viewDidLoad(){
super.viewDidLoad()
tableView.register(UITableViewCell.self, forCellReuseIdentifier:"cell")applySnapshot(animatingDifferences:false){FHSection(.main){Item(title:"First Item")Item(title:"Second Item")}FHSection(.detail){Item(title:"Third Item")}}}}

The cellProvider must be overwritten because the default implementation raises a fatal error. Do not forget to register the cell before you call applySnapshot(_:) the first time!


The cell selection can be implemented like that:

overridefunc tableView(_ tableView:UITableView, didSelectRowAt indexPath:IndexPath){letitem= dataSource.itemIdentifier(for: indexPath)
/*do your actions with the selected item*/
}

Customize Header and Footer Views (collection view only)

In order to use custom header or footer views, the supplementaryViewProvider property must be overwritten.

overridevarsupplementaryViewProvider:UICollectionViewDiffableDataSource<Section,Item>.SupplementaryViewProvider?{return{ collectionView, kind, indexPath inletheaderView= collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier:"customHeader", for: indexPath)as?CustomHeaderswitchself.dataSource.snapshot().sectionIdentifiers[indexPath.section]{case.main:
headerView?.backgroundColor =.systemGreen
case.detail:
headerView?.backgroundColor =.systemPink
}return headerView
}}

Do not forget to register the supplementary view before you call applySnapshot(_:) the first time!

collectionView.register(CustomHeader.self, forSupplementaryViewOfKind:UICollectionView.elementKindSectionHeader, withReuseIdentifier:"customHeader")

Custom Data Source

In case you want to change the behavior of the title creation or you want to use section index titles and other features you have to subclass the appropriate data source. For the table view it could look something like that:

classCustomDataSource:UITableViewDiffableDataSource<Section,Item>{overridefunc tableView(_ tableView:UITableView, titleForHeaderInSection section:Int)->String?{switchsnapshot().sectionIdentifiers[section]{case.main:return"Main"case.detail:return"Detail"}}}

Use UICollectionViewDiffableDataSource for collection view.

So that it can be used in our view controller we have to create a lazy var of this and override the dataSource property with it.

lazy varcustomDataSource=CustomDataSource(tableView: tableView, cellProvider: cellProvider)overridevardataSource:UITableViewDiffableDataSource<Section,Item>{return customDataSource
}

Custom applySnapshot(_:)

You are not forced to use applySnapshot(_:) in combination with FHDiffableDataSourceSection array to apply snapshots to your dataSource. You can override the applySnapshot(_:) to change its behavior, create your own applySnapshot() method or do it manually as follows:

varsnapshot=FHSnapshot()
snapshot.appendSections([.main,.detail])
snapshot.appendItems([Item(title:"Main Item")], toSection:.main)
snapshot.appendItems([Item(title:"Detail Item")], toSection:.detail)
dataSource.apply(snapshot, animatingDifferences:true, completion:nil)

Section & Item builder

In addition to the traditional Array way there is a result builder for both the Section's and Item's creation.

Array
applySnapshot([FHSection(.main, items:[Item(title:"First Item"),Item(title:"Second Item"),]),FHSection(.detail, items:[Item(title:"Third Item"),]),])
Result Builder
applySnapshot{FHSection(.main){Item(title:"First Item")Item(title:"Second Item")}FHSection(.detail){Item(title:"Third Item")}}

License

FHConstraints is available under the MIT license. See the LICENSE file for more info.

About

UITableViewController and UICollectionViewController based on a DiffableDataSource.

Topics

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages