在iOS 10.0上,UICollectionView默认预取单元格。这导致细胞准备好在屏幕上显示,但是被隐藏。这个question很好地描述了它。
以下代码将在其单元格可见或根本不存在时成功取消选择索引路径。如果单元格存在且被隐藏,则将取消选择索引路径,但单元格将停留在选定状态,直到重用为止。
collectionView!.deselectItem(at: indexPath, animated: false)
在iOS 9上或在iOS 10.0上使用isPrefetchingEnabled = false
禁用预取时,此问题不会退出。
这是UICollectionView中的错误还是我误解了deselectItem应该如何工作?
以下是UICollectionViewController子类的完整代码,它通过以下步骤演示此行为:
import UIKit
private let reuseIdentifier = "Cell"
class CollectionViewController: UICollectionViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
let button = UIButton(frame: CGRect(x: 10, y: 30, width: 360, height: 44))
button.backgroundColor = #colorLiteral(red: 0.9686274529, green: 0.78039217, blue: 0.3450980484, alpha: 1)
button.setTitleColor(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1), for: .normal)
button.setTitleColor(#colorLiteral(red: 0.05882352963, green: 0.180392161, blue: 0.2470588237, alpha: 1), for: .highlighted)
button.setTitle("Deselect Cell", for: .normal)
button.addTarget(self, action: #selector(CollectionViewController.buttonPress), for: .touchUpInside)
view.addSubview(button)
}
func buttonPress() {
for indexPath in collectionView!.indexPathsForSelectedItems ?? [IndexPath]() {
let cell = collectionView!.cellForItem(at: indexPath)
NSLog("Deselecting indexPath: %@, cell: %@", indexPath.description, cell?.frame.debugDescription ?? "not visible")
collectionView!.deselectItem(at: indexPath, animated: false)
}
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 300
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
cell.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
cell.selectedBackgroundView = UIView(frame: cell.bounds)
cell.selectedBackgroundView!.backgroundColor = #colorLiteral(red: 0.9254902005, green: 0.2352941185, blue: 0.1019607857, alpha: 1)
return cell
}
}
答案 0 :(得分:1)
据我所知,这是UICollectionView
中的一个错误,我自己也开了一个雷达。您可能也希望这样做以施加更大的压力。
即使在预取之前,集合视图也不会忘记取消选择不可见的单元格。即使cellForItemAtIndexPath:
也声明它会为不可见的单元格返回nil
。
但是在预取之前,只要一个单元格离开内容视图,它就会被添加到重用池中,当你向后滚动时,你会得到一个重用的单元格,它会重置所选的状态。
现在,该单元格仍然被加载,并且在重新使用之前不会重置,通过进一步滚动,超出预取区域。
要解决此问题,您可以将prefetchingEnabled
设置为NO
并失去其优势,或在信号出现时更新选择状态 -
- (void)collectionView:(UICollectionView *)collectionView
willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
if (!cell.isSelected) {
return;
}
if ([[collectionView indexPathsForSelectedItems] containsObject:indexPath]) {
return;
}
cell.selected = NO;
}
这似乎不会降低性能。