Mehrere Einfrierungen in der Sammlungsansicht
Posted: 19 Jan 2025, 17:23
Ich habe eine Sammlungsansicht mit UICollectionViewCompositionalLayout. In meiner Sammlung befinden sich Artikel mit Bildern. Wenn ich meine App starte, wird die Sammlungsansicht angezeigt. Und wenn ich anfange zu scrollen, friere ich mehrmals ein. Aber als ich durch die gesamte Sammlung scrollte, verschwanden die Einfrierungen. Ich denke, dass das Einfrieren nach dem vollständigen Scrollen der Sammlung verschwindet, weil die Bilder bereits geladen sind. Aber wie kann ich das Problem beheben, damit es nach dem Start der App und dem ersten Scrollen der Sammlung nicht einfriert?
Video zur Reproduktion des Problems:
https://drive.google.com/file/d/145Bl2O ... share_link
Es gibt viel Code in der App, also habe ich das Projekt auf GitHub gepostet:
https://github.com/user234567890354678/carousel
Hauptcode:
Sammlungsansichtszelle
Sammlungscontroller
Was habe ich versucht, um dieses Problem zu lösen?
Ich habe das gleiche Problem in einer UITableView mit vielen Bildern. Um dies zu beheben, verwende ich diesen Code:
Und nach dem Ausführen werden die Bilder nach ein paar Sekunden in die Zellen geladen und danach kann ich durch die Tabelle scrollen, ohne einzufrieren. Dann habe ich versucht, diesen Code für meine betreffende Sammlungsansicht wie folgt anzuwenden:
Aber das hat mir überhaupt nicht geholfen. Was mache ich falsch?
Video zur Reproduktion des Problems:
https://drive.google.com/file/d/145Bl2O ... share_link
Es gibt viel Code in der App, also habe ich das Projekt auf GitHub gepostet:
https://github.com/user234567890354678/carousel
Hauptcode:
Sammlungsansichtszelle
Code: Select all
class CVCell: UICollectionViewCell, SelfConfiguringCell {
func configure(with item: Item) {
title.text = item.title
textView.backgroundColor = UIColor(item.backgroundColor)
textView.layer.borderColor = UIColor(item.borderColor).cgColor
titleImageView.image = UIImage(named: item.titleImage)
imageView.image = UIImage(named: item.image)
}
}
Code: Select all
class CVController: UIViewController, UICollectionViewDelegate {
var collectionView: UICollectionView!
var dataSource: UICollectionViewDiffableDataSource?
let sections = Bundle.main.decode([Section].self, from: "img1.json")
func createDataSource() {
dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { collectionView, indexPath, item in
switch self.sections[indexPath.section].identifier {
case "carouselCell":
let cell = self.configure(CarouselCell.self, with: item, for: indexPath)
return cell
default: return self.configure(CarouselCell.self, with: item, for: indexPath)
}
}
}
func configure(_ cellType: T.Type, with item: Item, for indexPath: IndexPath) -> T {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellType.reuseIdentifier, for: indexPath) as? T else { fatalError("\(cellType)") }
cell.configure(with: item)
return cell
}
func reloadData() {
var snapshot = NSDiffableDataSourceSnapshot()
snapshot.appendSections(sections)
for section in sections { snapshot.appendItems(section.item, toSection: section) }
dataSource?.apply(snapshot)
}
func setupCollectionView() {
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: createCompositionalLayout())
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
collectionView.isScrollEnabled = false
collectionView.delegate = self
collectionView.contentInsetAdjustmentBehavior = .never
view.addSubview(collectionView)
collectionView.register(CarouselCell.self, forCellWithReuseIdentifier: CarouselCell.reuseIdentifier)
createDataSource()
reloadData()
}
func createCompositionalLayout() -> UICollectionViewLayout {
UICollectionViewCompositionalLayout { (sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), //
heightDimension: .fractionalHeight(1)) //
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupWidth = (layoutEnvironment.container.contentSize.width * 1.05)/3
let groupSize = NSCollectionLayoutSize(widthDimension: .absolute(groupWidth), //
heightDimension: .absolute(groupWidth)) //
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.contentInsets = NSDirectionalEdgeInsets(
top: (layoutEnvironment.container.contentSize.height/2) - (groupWidth/2),
leading: 0,
bottom: 0,
trailing: 0)
section.interGroupSpacing = 64
section.orthogonalScrollingBehavior = .groupPagingCentered
section.contentInsetsReference = .none
section.visibleItemsInvalidationHandler = { (items, offset, environment) in
items.forEach { item in
let distanceFromCenter = abs((item.frame.midX - offset.x) - environment.container.contentSize.width / 2.0)
let minScale: CGFloat = 0.7
let maxScale: CGFloat = 1.1
let scale = max(maxScale - (distanceFromCenter / environment.container.contentSize.width), minScale)
item.transform = CGAffineTransform(scaleX: scale, y: scale)
}
}
return section
}
}
func reloadItem(indexPath: IndexPath) {
guard let needReloadItem = dataSource!.itemIdentifier(for: indexPath) else { return }
var snapshot = NSDiffableDataSourceSnapshot()
snapshot.appendSections(sections)
for section in sections { snapshot.appendItems(section.item, toSection: section) }
dataSource?.apply(snapshot)
snapshot.reloadItems([needReloadItem])
dataSource?.apply(snapshot, animatingDifferences: false)
}
}
Ich habe das gleiche Problem in einer UITableView mit vielen Bildern. Um dies zu beheben, verwende ich diesen Code:
Code: Select all
func loadImageAsync(imageName: String, completion: @escaping (UIImage) -> ()) {
DispatchQueue.global(qos: .userInteractive).async {
guard let image = UIImage(named: imageName) else {return}
DispatchQueue.main.async {
completion(image)
}
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! RecipesViewCell
loadImageAsync(imageName: imageName) { (image) in
guard cell.imageName == imageName else { return }
cell.cardImageView.image = image
}
}
Code: Select all
class CVCell: UICollectionViewCell, SelfConfiguringCell {
func configure(with item: Item) {
loadImageAsync(imageName: item.image) { (image) in
self.imageView.image = image
}
}
func loadImageAsync(imageName: String, completion: @escaping (UIImage) -> ()) {
DispatchQueue.global(qos: .userInteractive).async {
guard let image = UIImage(named: imageName) else {return}
DispatchQueue.main.async {
completion(image)
}
}
}
}