Mehrere Einfrierungen in der SammlungsansichtIOS

Programmierung für iOS
Guest
 Mehrere Einfrierungen in der Sammlungsansicht

Post by Guest »

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

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)
}
}
Sammlungscontroller

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)
}

}
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:

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
}
}
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:

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)
}
}
}

}
Aber das hat mir überhaupt nicht geholfen. Was mache ich falsch?

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post