gpt4 book ai didi

ios - 具有组合布局和差异数据源的 UICollectionView 在滚动时消失

转载 作者:行者123 更新时间:2023-12-05 07:04:18 28 4
gpt4 key购买 nike

我目前有一个 UICollectionView,我正在使用组合布局和 Diffable 数据源。我并没有做任何疯狂的事情,只是将 150 个单元格加载到其中并定义了 4 列布局。每当我点击 collectionview 滚动它似乎正在消失的项目时,我似乎遇到了一些奇怪的行为......下面是我的文件,其中包含我正在使用的整个代码,以便您可以复制并粘贴它并看到这个奇怪的行为。有谁知道为什么会发生这种情况?

import UIKit

class ViewController: UIViewController {

private lazy var myCollectionViewLayout = MyCollectionViewLayout()

override func viewDidLoad() {
super.viewDidLoad()
setup()
// Do any additional setup after loading the view.
}
}

private extension ViewController {

func setup() {

let collectionVw = UICollectionView(frame: .zero, collectionViewLayout: myCollectionViewLayout.createLayout())
collectionVw.translatesAutoresizingMaskIntoConstraints = false
collectionVw.register(MyCustomCell.self, forCellWithReuseIdentifier: MyCustomCell.cellId)

self.view.addSubview(collectionVw)

NSLayoutConstraint.activate([
collectionVw.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
collectionVw.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor),
collectionVw.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
collectionVw.trailingAnchor.constraint(equalTo: self.view.trailingAnchor)
])

let dataSource = UICollectionViewDiffableDataSource<Int, UUID>(collectionView: collectionVw) { (collectionView, indexPath, item) -> UICollectionViewCell? in

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MyCustomCell.cellId, for: indexPath) as? MyCustomCell
cell?.configure(at: indexPath.row)
return cell
}

collectionVw.dataSource = dataSource

var snapshot = NSDiffableDataSourceSnapshot<Int, UUID>()

snapshot.appendSections([0])

Range(0...150).forEach { item in
snapshot.appendItems([UUID()], toSection: 0)
}

dataSource.apply(snapshot, animatingDifferences: true)
}
}

class MyCollectionViewLayout {

func createLayout() -> UICollectionViewCompositionalLayout {

let layout = UICollectionViewCompositionalLayout { (sectionIndex: Int, layoutEnv: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in

let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.25),
heightDimension: .fractionalHeight(1))

let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1),
heightDimension: .fractionalWidth(0.25))

let item = NSCollectionLayoutItem(layoutSize: itemSize)

let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize,
subitem: item,
count: 4)
group.interItemSpacing = .fixed(16)

let section = NSCollectionLayoutSection(group: group)

section.interGroupSpacing = 16
section.contentInsets = NSDirectionalEdgeInsets(top: 0,
leading: 16,
bottom: 0,
trailing: 16)

return section
}

return layout

}
}

class MyCustomCell: UICollectionViewCell {

static let cellId = "MyCustomCell"

private var lbl: UILabel?

func configure(at index: Int) {

self.contentView.layer.cornerRadius = 8
self.contentView.backgroundColor = .blue

lbl = UILabel()
lbl?.translatesAutoresizingMaskIntoConstraints = false
lbl?.text = index.description
lbl?.textAlignment = .center
lbl?.font = .preferredFont(forTextStyle: .headline)

self.contentView.addSubview(lbl!)

NSLayoutConstraint.activate([
lbl!.topAnchor.constraint(equalTo: self.contentView.topAnchor),
lbl!.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor),
lbl!.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor),
lbl!.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor)
])

}

override func prepareForReuse() {
super.prepareForReuse()
lbl?.removeFromSuperview()
}
}

最佳答案

原因是您的数据源是您的setup 方法中的局部变量(let dataSource...)。因此它只工作一次,最初填充 Collection View ,然后消失在一阵烟雾中,留下没有数据的 Collection View 。

数据源必须是 View Controller 的一个属性,这样它才能持久存在!一旦做出改变,一切都会好起来的。

这样做实际上有点棘手,因为数据源取决于 Collection View 。所以你必须使用惰性实例化。您使用空布局创建 Collection View ,并在设置的第一步将所有内容连接在一起。

这是对代码的最小重写;查找我解释更改的评论。

import UIKit


class ViewController: UIViewController {
// delete; this is pointless
// private lazy var myCollectionViewLayout = MyCollectionViewLayout()

override func viewDidLoad() {
super.viewDidLoad()
setup()
}

// need persistent pointer to collection view
let collectionVw = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewLayout())

// need persistent pointer to data source
lazy var dataSource = UICollectionViewDiffableDataSource<Int, UUID>(collectionView: collectionVw) { (collectionView, indexPath, item) -> UICollectionViewCell? in

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MyCustomCell.cellId, for: indexPath) as? MyCustomCell
cell?.configure(at: indexPath.row)
return cell
}

}

private extension ViewController {

func setup() {


// let collectionVw = UICollectionView(frame: .zero, collectionViewLayout: myCollectionViewLayout.createLayout())
// everything is persistent, now just hook them together
collectionVw.collectionViewLayout = MyCollectionViewLayoutMaker.createLayout()

collectionVw.translatesAutoresizingMaskIntoConstraints = false
collectionVw.register(MyCustomCell.self, forCellWithReuseIdentifier: MyCustomCell.cellId)

self.view.addSubview(collectionVw)

NSLayoutConstraint.activate([
collectionVw.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
collectionVw.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor),
collectionVw.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
collectionVw.trailingAnchor.constraint(equalTo: self.view.trailingAnchor)
])

// let dataSource = UICollectionViewDiffableDataSource<Int, UUID>(collectionView: collectionVw) { (collectionView, indexPath, item) -> UICollectionViewCell? in
//
// let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MyCustomCell.cellId, for: indexPath) as? MyCustomCell
// cell?.configure(at: indexPath.row)
// return cell
// }

collectionVw.dataSource = dataSource

var snapshot = NSDiffableDataSourceSnapshot<Int, UUID>()

snapshot.appendSections([0])

Range(0...150).forEach { item in
snapshot.appendItems([UUID()], toSection: 0)
}

dataSource.apply(snapshot, animatingDifferences: true)
}
}

class MyCollectionViewLayoutMaker {
// make this static; the class is not the layout, it serves no purpose except as a factory
static func createLayout() -> UICollectionViewCompositionalLayout {

let layout = UICollectionViewCompositionalLayout { (sectionIndex: Int, layoutEnv: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in

let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.25),
heightDimension: .fractionalHeight(1))

let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1),
heightDimension: .fractionalWidth(0.25))

let item = NSCollectionLayoutItem(layoutSize: itemSize)

let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize,
subitem: item,
count: 4)
group.interItemSpacing = .fixed(16)

let section = NSCollectionLayoutSection(group: group)

section.interGroupSpacing = 16
section.contentInsets = NSDirectionalEdgeInsets(top: 0,
leading: 16,
bottom: 0,
trailing: 16)

return section
}

return layout

}
}

class MyCustomCell: UICollectionViewCell {

static let cellId = "MyCustomCell"

private var lbl: UILabel?

func configure(at index: Int) {

self.contentView.layer.cornerRadius = 8
self.contentView.backgroundColor = .blue

lbl = UILabel()
lbl?.translatesAutoresizingMaskIntoConstraints = false
lbl?.text = index.description
lbl?.textAlignment = .center
lbl?.font = .preferredFont(forTextStyle: .headline)

self.contentView.addSubview(lbl!)

NSLayoutConstraint.activate([
lbl!.topAnchor.constraint(equalTo: self.contentView.topAnchor),
lbl!.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor),
lbl!.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor),
lbl!.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor)
])

}

override func prepareForReuse() {
super.prepareForReuse()
lbl?.removeFromSuperview()
}
}

关于ios - 具有组合布局和差异数据源的 UICollectionView 在滚动时消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62957098/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com