UICollection 的 IndexPath 到底是啥
Posted
技术标签:
【中文标题】UICollection 的 IndexPath 到底是啥【英文标题】:What exactly is the IndexPath of a UICollectionUICollection 的 IndexPath 到底是什么 【发布时间】:2018-01-30 16:33:01 【问题描述】:我在使用 UICollectionViews 时遇到了 2 个问题,并且我以某种方式相信它在这两种情况下都与 IndexPath 相关,但是我真的不知道何时调用 IndexPath 或它究竟做了什么以及何时更新或更改。 无论如何,这是我的问题: 1. 不知何故Indexpath多次为0?Youtube VIDEO showing behavior
对于这种特殊行为,代码如下:
extension PointAllocVC: UICollectionViewDelegate, UICollectionViewDataSource
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
return (playerArray?.count)!
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "playerCell", for: indexPath) as! PointAllocCell
cell.cellDelegate = self
cell.cellIndex = indexPath.row
cell.nameLabel.text = playerArray![indexPath.row].alias
cell.scoreLabel.text = String(currentScore[indexPath.row])
cell.minusBtn.layer.cornerRadius = 15
cell.plusBtn.layer.cornerRadius = 15
cell.ptsRemaining = pointsToAllocate
cell.ptsUsed = abs(pointsUsedInCells[indexPath.row])
if indexPath.row == 0
cell.isSelf = true
cell.layer.borderWidth = 5
cell.layer.borderColor = UIColor.blue.cgColor
else
cell.isSelf = false
cell.updatedButtons()
return cell
如您所见,只有在 INDEXPATH.ROW == 0 单元格应该有边框(因为那是当前用户)。但是,当我突然单击按钮(请参阅下面的按钮逻辑)时,它们都是索引路径 == 0?
class PointAllocCell: UICollectionViewCell
var isSelf: Bool = false
var cellIndex: Int?
var ptsRemaining: Int = 0
var ptsUsed: Int = 0
var cellDelegate: PointsAllocDelegate?
@IBAction func plusTapped(_ sender: Any)
if cellDelegate != nil
cellDelegate!.plusTapReported(fromCell: cellIndex!)
updatedButtons()
@IBAction func minusTapped(_ sender: Any)
if cellDelegate != nil
cellDelegate!.minusTapReported(fromCell: cellIndex!)
updatedButtons()
func updatedButtons()
switch (ptsRemaining, ptsUsed)
case (0,0):
plusBtn.isEnabled = false
minusBtn.isEnabled = false
case (0,_):
if isSelf
plusBtn.isEnabled = false
minusBtn.isEnabled = true
else
plusBtn.isEnabled = true
minusBtn.isEnabled = false
case (_,0):
if isSelf
plusBtn.isEnabled = true
minusBtn.isEnabled = false
else
plusBtn.isEnabled = false
minusBtn.isEnabled = true
default:
plusBtn.isEnabled = true
minusBtn.isEnabled = true
pointLabel.text = String(ptsUsed)
最后是委托:
extension PointAllocVC: PointsAllocDelegate
func plusTapReported(fromCell: Int)
if fromCell == 0
//this is self
pointsToAllocate -= 1
pointsUsedInCells[fromCell] += 1
else
pointsToAllocate += 1
pointsUsedInCells[fromCell] += 1
reloadCollection()
reloadLabels()
func minusTapReported(fromCell: Int)
if fromCell == 0
//this is self
pointsToAllocate += 1
pointsUsedInCells[fromCell] -= 1
else
pointsToAllocate -= 1
pointsUsedInCells[fromCell] -= 1
reloadCollection()
reloadLabels()
现在。第二个问题,当我执行以下操作时,我得到了它
playerArray.remove(at: gKPlayerArray.index(of: playerDed)!)
这行代码没有做任何事情,但是当我调用“reloadData”之后,我发现 IndexPath.row 超出范围(由于某种原因,它仍然认为 playerArray 的大小为 X+1即使我在调用它之前删除了一个项目。
【问题讨论】:
关于您的第一个问题,您还必须在else
正文中明确设置边框,因为单元格被重复使用。
【参考方案1】:
一个单元永远不需要知道它自己的 indexPath。这是一个非常糟糕的设计。
重构您的代码,这样您就不会将行或 indexPath 传递给单元格。
更改您的单元委托协议以传递实际单元,而不是 Int
。
现在将告知实际实现委托方法的类代表哪个单元格调用委托方法,如果需要,该类可以确定单元格的 indexPath。
您还需要更新您的cellForItemAt
。
这段代码有问题:
if indexPath.row == 0
cell.isSelf = true
cell.layer.borderWidth = 5
cell.layer.borderColor = UIColor.blue.cgColor
else
cell.isSelf = false
每当您设置一个属性时,您必须始终为其他条件重置它。
if indexPath.row == 0
cell.isSelf = true
cell.layer.borderWidth = 5
cell.layer.borderColor = UIColor.blue.cgColor
else
cell.isSelf = false
cell.layer.borderWidth = 0
您不需要重置 0 宽度边框的颜色。
【讨论】:
你能详细说明一下吗?我如何将单元格的索引发送回委托,以便它更新分数数组?就像我的函数是cellDelegate!.minusTapReported(fromCell: self)
但那会返回什么?什么类型的数据是“自我”?
您不会将索引发送给代理。这就是我的全部观点。应为代表提供单元格,而不是索引。然后,委托可以询问集合视图,该单元格的 indexPath 是什么。
好的,所以我发送“self”,然后如何将其转换为 indexPath?你有什么可以指点我的例子吗?顺便谢谢你!
查看UICollectionView
的文档。有一种明显的方法可以获取单元格的 indexPath。
func indexPath(for: UICollectionViewCell)
返回指定单元格的索引路径。然而。我如何将其传递给代表?如果我返回“self”,我会收到一堆错误,并且我无法告诉委托方法 func minusTapReported(fromCell: UICollectionViewCell)
之类的东西,因为这也会引发错误 ** EDIT ** FOUND THE ISSUE。在委托 swift 文件中缺少 Import UIKit【参考方案2】:
@rmaddy 在回答中没有提到一件事 - 因为您使用的是 UICollectionView
,所以您不应该使用 IndexPath
的 row
属性,而应该使用 item
属性。鉴于集合视图的性质及其在布局单元格方面的灵活性,系统无法识别“行”。使用UITableView
时应使用row
属性。
var 行:整数 标识表视图部分中的行的索引号。var item: Int 标识集合视图部分中的项目的索引号。
https://developer.apple.com/documentation/foundation/nsindexpath
【讨论】:
以上是关于UICollection 的 IndexPath 到底是啥的主要内容,如果未能解决你的问题,请参考以下文章
iOS解决UICollectionView中使用reloadItemsAtIndexPaths进行局部cell更新导致视图重叠问题
在单独的 UICollection 类中使用未解析的标识符“UICollection”