Last active
August 20, 2020 09:25
-
-
Save tomasharkema/b633709c1fd8edb5b462f76bde4f807c to your computer and use it in GitHub Desktop.
UICollectionViewDiffableDataSource iOS 12
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// DataSource.swift | |
// | |
// Created by Tomas Harkema on 06/06/2019. | |
// Copyright © 2019 Tomas Harkema. All rights reserved. | |
// | |
import UIKit | |
import DeepDiff // https://github.com/onmyway133/DeepDiff | |
enum Section: Hashable { | |
case empty | |
} | |
class DataSource<Item: Hashable & DiffAware>: NSObject { | |
static func create(collectionView: UICollectionView, cellProvider: @escaping (UICollectionView, IndexPath, Item) -> UICollectionViewCell?) -> DataSource<Item> { | |
if #available(iOS 13, *) { | |
return NewDataSource(collectionView: collectionView, cellProvider: cellProvider) | |
} else { | |
return OldDataSource(collectionView: collectionView, cellProvider: cellProvider) | |
} | |
} | |
func apply(newValue: [Item]) { | |
fatalError() | |
} | |
func itemIdentifier(for indexPath: IndexPath) -> Item? { | |
fatalError() | |
} | |
} | |
@available(iOS 13, *) | |
class NewDataSource<Item: Hashable & DiffAware>: DataSource<Item> { | |
private let dataSource: UICollectionViewDiffableDataSource<Section, Item> | |
init(collectionView: UICollectionView, cellProvider: @escaping (UICollectionView, IndexPath, Item) -> UICollectionViewCell?) { | |
dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView, cellProvider: cellProvider) | |
super.init() | |
} | |
override func apply(newValue: [Item]) { | |
let snapshot = NSDiffableDataSourceSnapshot<Section, Item>() | |
snapshot.appendSections([.empty]) | |
snapshot.appendItems(newValue) | |
dataSource.apply(snapshot) | |
} | |
override func itemIdentifier(for indexPath: IndexPath) -> Item? { | |
return dataSource.itemIdentifier(for: indexPath) | |
} | |
} | |
@available(iOS, deprecated: 12.4, obsoleted: 12.4) | |
class OldDataSource<Item: Hashable & DiffAware>: DataSource<Item>, UICollectionViewDataSource { | |
private let collectionView: UICollectionView | |
private var backingStore = [Item]() | |
private let cellProvider: (UICollectionView, IndexPath, Item) -> UICollectionViewCell? | |
init(collectionView: UICollectionView, cellProvider: @escaping (UICollectionView, IndexPath, Item) -> UICollectionViewCell?) { | |
self.collectionView = collectionView | |
self.cellProvider = cellProvider | |
super.init() | |
collectionView.dataSource = self | |
} | |
func numberOfSections(in collectionView: UICollectionView) -> Int { | |
return 1 | |
} | |
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { | |
return backingStore.count | |
} | |
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { | |
return cellProvider(collectionView, indexPath, backingStore[indexPath.row])! | |
} | |
override func apply(newValue: [Item]) { | |
DispatchQueue.main.async { | |
let changes = diff(old: self.backingStore, new: newValue) | |
self.collectionView.reload(changes: changes, updateData: { | |
self.backingStore = newValue | |
}) | |
} | |
} | |
override func itemIdentifier(for indexPath: IndexPath) -> Item? { | |
return backingStore[indexPath.item] | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment