ios - Swift:如何清除 collectionView 以便在 collectionViewCell 中重用
问题描述
我有一个collectionView,它位于collectionViewCell 内,并且在重用单元格时collectionView 没有被正确清除。
代码:
class TweetCell: UICollectionViewCell {
lazy var mediaCollectionView: UICollectionView = {
let size = NSCollectionLayoutSize(
widthDimension: NSCollectionLayoutDimension.fractionalWidth(1),
heightDimension: NSCollectionLayoutDimension.fractionalHeight(1)
)
let item = NSCollectionLayoutItem(layoutSize: size)
let group = NSCollectionLayoutGroup.horizontal(layoutSize: size, subitem: item, count: 1)
let section = NSCollectionLayoutSection(group: group)
section.interGroupSpacing = 4
section.orthogonalScrollingBehavior = .paging
let layout = UICollectionViewCompositionalLayout(section: section)
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.translatesAutoresizingMaskIntoConstraints = false
cv.dataSource = self
cv.delegate = self
cv.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
return cv
}()
var tweet: Tweet? {
didSet {
if let tweet = tweet {
//Setup other UI elements
nameLabel.text = tweet.name ?? ""
twitterHandleLabel.text = tweet.twitterHandle ?? ""
profileImageView.sd_setImage(with: profileImageUrl)
}
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
func setupViews() {
let mainStack = UIStackView(arrangedSubviews: [
userHStack,
mediaCollectionView,
bottomHStack
])
mainStack.axis = .vertical
mainStack.translatesAutoresizingMaskIntoConstraints = false
addSubview(mainStack)
mainStack.topAnchor.constraint(equalTo: topAnchor).isActive = true
mainStack.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
mainStack.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
mainStack.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
//Must lower priority otherwise autolayout will complain
heightConstraint = mediaCollectionView.heightAnchor.constraint(equalToConstant: 0)
heightConstraint.priority = UILayoutPriority(999)
}
override func prepareForReuse() {
super.prepareForReuse()
mediaCollectionView.reloadData()
tweet = nil
}
}
extension TweetCell: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return tweet?.mediaArray?.count ?? 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
cell.backgroundColor = .systemPink
return cell
}
}
//HomeController that displays the feed
class HomeController: UIViewController {
lazy var collectionView: UICollectionView = {
let size = NSCollectionLayoutSize(
widthDimension: NSCollectionLayoutDimension.fractionalWidth(1),
heightDimension: NSCollectionLayoutDimension.estimated(500)
)
let item = NSCollectionLayoutItem(layoutSize: size)
let group = NSCollectionLayoutGroup.horizontal(layoutSize: size, subitem: item, count: 1)
let section = NSCollectionLayoutSection(group: group)
let layout = UICollectionViewCompositionalLayout(section: section)
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.translatesAutoresizingMaskIntoConstraints = false
cv.dataSource = self
cv.delegate = self
cv.register(TweetCell.self, forCellWithReuseIdentifier: "cell")
return cv
}()
var tweets: [Tweet]?
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
fetchData()
}
func fetchData() {
let accessToken = UserDefaults.standard.string(forKey: Constants.UserDefaults.UserAccessTokenKey) ?? ""
let secretToken = UserDefaults.standard.string(forKey: Constants.UserDefaults.UserSecretTokenKey) ?? ""
TwitterClient.shared.fetchHomeTimeline(accessToken: accessToken, secretToken: secretToken) { (tweets) in
self.tweets = tweets
DispatchQueue.main.async {
self.collectionView.reloadData()
}
}
}
func setupViews() {
view.addSubview(collectionView)
collectionView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
}
extension HomeController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return tweets?.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! TweetCell
cell.tweet = tweets?[indexPath.item]
return cell
}
}
如果我将其硬编码numberOfItemsInSection
为一个随机整数,mediaCollectionView
则会正确显示单元格的数量。但是,当动态设置为 时tweet?.mediaArray?.count
,单元格的数量不再正确。我相信这是由于 collectionViewCell 的重用,因为当我滚动浏览 collectionView 时,这些单元格的计数开始跳跃。
如何正确重置 TweetCell 中的 collectionView?
更新:
尝试2: -
override func prepareForReuse() {
mediaCollectionView.reloadData()
tweet = nil
super.prepareForReuse()
}
上面的工作也不太顺利。
解决方案
嗯。我认为您必须在单元内实现常规协议并重构所有代码。
我的意思是 UICollectionViewDelegate(或 flynDelegate)和 UICollectionViewDataSource。
class TweetCell: UICollectionViewCell,UICollectionViewDelegate,UICollectionViewDataSource {
...
推荐阅读
- node.js - 会话不会在快递中保存不同路线的数据
- javascript - 在 html 中创建和调用动态日期链接
- python - 将透明度和颜色应用于雷达图表 Python-pptx
- wordpress - WPBakery Wordpress DOM元素的重复
- c# - 错误无法将 DBNULL 对象转换为其他 C# Datagridview 类型
- java - 当玩家转动(旋转)时,KeyPressed 方法不会更新
- bootstrap-4 - 带有灯箱弹出窗口的引导轮播,包括滑块
- oracle-apex - 在 Oracle Apex 应用程序中启动触发器的问题
- ajax - 使用 AJAX 进行 GET 的 Razor Pages PageModel 绑定
- python - 我需要在图表上绘制很多 X,但是有没有办法不必直接指定颜色?