Open macistador opened 4 years ago
I am also very curious if support for this is coming.
It's strange that there has not been any answer on the issue since March. @Juanpe, could you, please, response
@Juanpe hello ?! Please response on this issue
SkeletonView
is currently working with DiffableDataSource
when setting false to reloadDataAfter
when hiding skeleton view. I did nothing special beside that in order to have a working skeleton tableview
@tbaranes Hi! What do you mean by "is currently working"? As far as I know, you need to implement SkeletonCollectionViewDataSource to make it work with UICollectionView
Exactly, you need to inherit from UITableViewDiffableDataSource
and conforms to SkeletonTableViewDataSource
. In my case I was using a tableview, but I think it will be the same for a collection view.
class MyDataSource: UITableViewDiffableDataSource<Int, Model> {
init(tableView: UITableView) {
super.init(tableView: tableView) { tableView, indexPath, model in
// ...
}
}
}
// MARK: - SkeletonCollectionViewDataSource
extension MyDataSource: SkeletonTableViewDataSource {
func collectionSkeletonView(_ skeletonView: UITableView, cellIdentifierForRowAt indexPath: IndexPath) -> ReusableCellIdentifier {
"ReusableIdentifier"
}
}
Doing this will make skeleton working but as said before when hiding the skeleton you will need to set reloadDataAfter
to false, otherwise the skeleton won't be hidden:
if showSkeleton {
tableView.showAnimatedSkeleton()
} else {
tableView.hideSkeleton(reloadDataAfter: false)
}
@tbaranes Is there anything more to your example? I have the same code but the collectionSkeletonView
function is never called
@tbaranes solution doesn't work for me. I tried on v1.21.0
also does not work with collections version 1.25.2
I've tried @tbaranes's solution but I keep getting this error
*** Assertion failure in -[UITableView _performDiffableUpdate:], UITableView.m:19143
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'Attempted to apply updates to a table view from a UITableViewDiffableDataSource, but the table view's dataSource is not the UITableViewDiffableDataSource.
Table view: <
UITableView: 0x7f7d7d121400;
frame = (0 174.333; 390 521.333);
clipsToBounds = YES;
alpha = 0;
userInteractionEnabled = NO;
gestureRecognizers = <NSArray: 0x600000635bf0>;
animations = { opacity=<CABasicAnimation: 0x600000838a80>;
transition=<CATransition: 0x600000838ac0>; };
layer = <CALayer: 0x600000817900>;
contentOffset: {0, 0};
contentSize: {390, 422.33333333333331};
adjustedContentInset: {0, 0, 0, 0};
dataSource: <SkeletonView.SkeletonCollectionDataSource: 0x600001326340>
>'
so I guess it doesn't really work. Does anyone know another way to make SkeletonView work with diffable data sources?
@dsk1306 It looks like SkeletonView will swap to its own datasource for showing skeleton, so you need to hideSkeleton() before you call .apply()
on DiffableDataSource
Hi guys! I see there is a workaround, right? Please, could you provide an example code or gist with this workaround to help other users with the same problem? Thanks
Here is the testing code, base on @tbaranes solution
import UIKit
import SkeletonView
class ItemCell: UICollectionViewCell {
let titleLabel = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(titleLabel)
titleLabel.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
titleLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor)
])
isSkeletonable = true
contentView.isSkeletonable = true
titleLabel.isSkeletonable = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class DiffableDataSourceViewController: UIViewController {
let collectionViewLayout = UICollectionViewCompositionalLayout.list(using: .init(appearance: .plain))
lazy var collectionView: UICollectionView = {
return UICollectionView(frame: self.view.bounds, collectionViewLayout: collectionViewLayout)
}()
lazy var datasource = CollectionViewSkeletonDiffableDataSource<String, Int>(collectionView: self.collectionView) { collectionView, indexPath, item in
let cell = collectionView.dequeueConfiguredReusableCell(using: self.cellRegistration, for: indexPath, item: item)
cell.backgroundColor = UIColor(hue: CGFloat(item % 10) / 10, saturation: 0.5, brightness: 0.7, alpha: 1)
return cell
}
let cellRegistration = UICollectionView.CellRegistration<ItemCell, Int> { cell, IndexPath, value in
cell.titleLabel.text = String(value)
}
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(collectionView)
collectionView.frame = view.frame
collectionView.register(ItemCell.self, forCellWithReuseIdentifier: "cell")
collectionView.isSkeletonable = true
collectionView.dataSource = datasource
collectionView.showSkeleton()
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
var ss = NSDiffableDataSourceSnapshot<String, Int>()
ss.appendSections(["Section 1", "Section 2", "Section 3"])
ss.appendItems(Array((1..<10)), toSection: "Section 1")
ss.appendItems(Array((11..<20)), toSection: "Section 2")
ss.appendItems(Array((21..<30)), toSection: "Section 3")
self.collectionView.hideSkeleton()
self.datasource.apply(ss)
}
}
}
class CollectionViewSkeletonDiffableDataSource<Section: Hashable, Item: Hashable>: UICollectionViewDiffableDataSource<Section, Item>, SkeletonCollectionViewDataSource {
var cellIdentifier: String = "cell"
func collectionSkeletonView(_ skeletonView: UICollectionView, cellIdentifierForItemAt indexPath: IndexPath) -> ReusableCellIdentifier {
return cellIdentifier
}
func collectionSkeletonView(_ skeletonView: UICollectionView, prepareCellForSkeleton cell: UICollectionViewCell, at indexPath: IndexPath) {
(cell as? ItemCell)?.titleLabel.text = "XXX"
}
func collectionSkeletonView(_ skeletonView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 50
}
}
Hi guys! I see there is a workaround, right? Please, could you provide an example code or gist with this workaround to help other users with the same problem? Thanks
Hi there Juanpe, there should be a dedicated section in the Readme where it states how to use it with DiffableDataSource as this package is very helpful and versatile!
Thanks!
Hi guys! I see there is a workaround, right? Please, could you provide an example code or gist with this workaround to help other users with the same problem? Thanks
Hi there Juanpe, there should be a dedicated section in the Readme where it states how to use it with DiffableDataSource as this package is very helpful and versatile!
Thanks!
Hi @tsangaris 👋🏼 Yeah, I think it's a good idea. Would you like to do it? If not, I will add it ASAP 👍🏼
Hi guys! I see there is a workaround, right? Please, could you provide an example code or gist with this workaround to help other users with the same problem? Thanks
Hi there Juanpe, there should be a dedicated section in the Readme where it states how to use it with DiffableDataSource as this package is very helpful and versatile! Thanks!
Hi @tsangaris 👋🏼 Yeah, I think it's a good idea. Would you like to do it? If not, I will add it ASAP 👍🏼
@Juanpe I just switched to DiffableDatasource, so I will need some time to learn how to use it and proceed with Skeleton views. I am just working proactively, so I need to make sure I can switch the skeleton views as well.
I am not sure how long its going to take, but if i have something ready i will let you know. Or if you have something that can help us, please post it :wink:
Here is the testing code, base on @tbaranes solution
import UIKit import SkeletonView class ItemCell: UICollectionViewCell { let titleLabel = UILabel() override init(frame: CGRect) { super.init(frame: frame) contentView.addSubview(titleLabel) titleLabel.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), titleLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor) ]) isSkeletonable = true contentView.isSkeletonable = true titleLabel.isSkeletonable = true } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } class DiffableDataSourceViewController: UIViewController { let collectionViewLayout = UICollectionViewCompositionalLayout.list(using: .init(appearance: .plain)) lazy var collectionView: UICollectionView = { return UICollectionView(frame: self.view.bounds, collectionViewLayout: collectionViewLayout) }() lazy var datasource = CollectionViewSkeletonDiffableDataSource<String, Int>(collectionView: self.collectionView) { collectionView, indexPath, item in let cell = collectionView.dequeueConfiguredReusableCell(using: self.cellRegistration, for: indexPath, item: item) cell.backgroundColor = UIColor(hue: CGFloat(item % 10) / 10, saturation: 0.5, brightness: 0.7, alpha: 1) return cell } let cellRegistration = UICollectionView.CellRegistration<ItemCell, Int> { cell, IndexPath, value in cell.titleLabel.text = String(value) } override func viewDidLoad() { super.viewDidLoad() view.addSubview(collectionView) collectionView.frame = view.frame collectionView.register(ItemCell.self, forCellWithReuseIdentifier: "cell") collectionView.isSkeletonable = true collectionView.dataSource = datasource collectionView.showSkeleton() DispatchQueue.main.asyncAfter(deadline: .now() + 2) { var ss = NSDiffableDataSourceSnapshot<String, Int>() ss.appendSections(["Section 1", "Section 2", "Section 3"]) ss.appendItems(Array((1..<10)), toSection: "Section 1") ss.appendItems(Array((11..<20)), toSection: "Section 2") ss.appendItems(Array((21..<30)), toSection: "Section 3") self.collectionView.hideSkeleton() self.datasource.apply(ss) } } } class CollectionViewSkeletonDiffableDataSource<Section: Hashable, Item: Hashable>: UICollectionViewDiffableDataSource<Section, Item>, SkeletonCollectionViewDataSource { var cellIdentifier: String = "cell" func collectionSkeletonView(_ skeletonView: UICollectionView, cellIdentifierForItemAt indexPath: IndexPath) -> ReusableCellIdentifier { return cellIdentifier } func collectionSkeletonView(_ skeletonView: UICollectionView, prepareCellForSkeleton cell: UICollectionViewCell, at indexPath: IndexPath) { (cell as? ItemCell)?.titleLabel.text = "XXX" } func collectionSkeletonView(_ skeletonView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 50 } }
@tomcheung thank you for taking the time to write this example. Just a question: What if I want to show a different number of skeleton items in each section? For example:
"Section 1": show 4 skeleton items "Section 2": show 6 skeleton items "Section 3": show 1 skeleton item
Also, what if I want each section to have a different layout of skeleton item?
Is there a way I can access the dataSource's snapshot inside the CollectionViewSkeletonDiffableDataSource class?
Thank you in advance.
Hi
Do you plan to support iOS 13 new UICollectionViewDiffableDataSource ?
Thanks