UICollectionViewCell 重用导致不正确的 UISwitch 状态
Posted
技术标签:
【中文标题】UICollectionViewCell 重用导致不正确的 UISwitch 状态【英文标题】:UICollectionViewCell reuse causing incorrect UISwitch state 【发布时间】:2019-01-26 07:00:51 【问题描述】:我无法找到解决此问题的方法。
我在UICollectionViewCell
中使用UISwitch
,并且我正在传递一个布尔变量来设置开关。
条件是所有单元中一次只有一个开关必须打开。 但是当我打开一个开关时,另一个随机开关的色调会发生变化,这意味着它的状态发生了变化。
默认情况下,故事板中的开关状态为 ON,即使我将其设置为 OFF,也没有任何变化。
我不知道为什么会这样。
这是我的 cellForItemAtIndexPath
代码
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: AddEditItemPopupView.cellId, for: indexPath) as! DiscountCollectionViewCell
cell.delegate = self
let currentDiscount = allDiscounts[indexPath.item]
let shouldApplyDiscount = updatedDiscountId == currentDiscount.id
cell.updateCellWith(data: currentDiscount, applyDiscount: shouldApplyDiscount)
return cell
单元类的代码
func updateCellWith(data: DiscountModel, applyDiscount: Bool)
let name = data.title.replacingOccurrences(of: "Discount ", with: "")
self.titleLabel.text = String(format: "%@ (%.2f%%)", name, data.value)
self.switchApply.isOn = applyDiscount
self.switchApply.tag = data.id
数据源包含DiscountModel
的对象,如下所示:
id: Int!
title: String!
value: Double!
cell类内的开关值改变方法:
@IBAction func switchValueChanged(_ sender: UISwitch)
if sender.isOn
self.delegate?.switchValueDidChangeAt(index: sender.tag)
else
self.delegate?.switchValueDidChangeAt(index: 0)
视图控制器类中的委托方法:
func switchValueDidChangeAt(index: Int)
self.updatedDiscountId = index
self.discountCollectionView.reloadData()
【问题讨论】:
如果在没有滚动的情况下发生这种情况,则可能不是单元格重用。它是静态的还是动态的集合视图? 还有,什么是switchApply? @Chris switchApply 是 collectionViewCell 中 UISwitch 的一个出口。它是一个动态集合视图,当前仅包含 4 个适合 collectionView 宽度的单元格,是的,这是在不滚动的情况下发生的。那么是什么导致了这个问题呢? 我觉得这两行可能是问题所在(但不确定):let currentDiscount = ...
和 let shouldApplyDiscount = ...
你所做的有些问题。当您单击开关时,它会启动动画,但您会立即重新加载单元格,重置isOn
,因此取消动画。我会尝试if switchApply.isOn != applyDiscount switchApply.isOn = applyDiscount
或DispatchQueue.main.async self.switchApply.isOn = applyDiscount
。一种可能的解决方案是禁用开关上的交互并改为处理整个单元格上的点击(选择)。
【参考方案1】:
我建议对您的代码进行一些改进;
重新加载整个集合视图有点像霰弹枪 由于可能不应用折扣,因此您可能应该为您选择的折扣使用可选项,而不是“0” 使用Tag
通常会出现问题
我会使用类似的东西:
var currentDiscount: DiscountModel? = nil
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: AddEditItemPopupView.cellId, for: indexPath) as! DiscountCollectionViewCell
cell.delegate = self
let item = allDiscounts[indexPath.item]
self.configure(cell, forItem: item)
return cell
func configure(_ cell: DiscountCollectionViewCell, forItem item: DiscountModel)
cell.switchApply.isOn = false
let name = item.title.replacingOccurrences(of: "Discount ", with: "")
self.titleLabel.text = String(format: "%@ (%.2f%%)", name, item.value)
guard let selectedDiscount = self.currentDiscount else
return
cell.switchApply.isOn = selectedDiscount.id == item.id
func switchValueDidChangeIn(cell: DiscountCollectionViewCell, to value: Bool)
if value
if let indexPath = collectionView.indexPath(for: cell)
self.currentDiscount = self.allDiscounts[indexPath.item]
else
self.currentDiscount = nil
for indexPath in collectionView.indexPathsForVisibleItems
if let cell = collectionView.cellForItem(at: indexPath)
self.configure(cell, forItem: self.allDiscounts[indexPath.item])
在你的牢房里:
@IBAction func switchValueChanged(_ sender: UISwitch)
self.delegate?.switchValueDidChangeIn(cell:self, to: sender.isOn)
【讨论】:
以上是关于UICollectionViewCell 重用导致不正确的 UISwitch 状态的主要内容,如果未能解决你的问题,请参考以下文章
带有 UICollectionViewCell 的可重用 UITableViewCell
重用 UICollectionView 中的单元格时,会短暂显示重用 UICollectionViewCell 的旧内容
带有重用标识符的 UICollectionViewCell 初始化