【问题标题】: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 正文中明确设置边框,因为单元格被重复使用。

标签: ios arrays swift uicollectionview


【解决方案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,所以您不应该使用 IndexPathrow 属性,而应该使用 item 属性。鉴于集合视图的性质及其在布局单元格方面的灵活性,系统无法识别“行”。使用UITableView 时应使用row 属性。

var 行:整数 标识表视图部分中的行的索引号。
var item: Int 标识集合视图部分中的项目的索引号。

https://developer.apple.com/documentation/foundation/nsindexpath

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-06
    • 2013-05-05
    • 2010-11-19
    • 2012-06-16
    • 2011-04-02
    • 2016-04-13
    • 2012-03-07
    相关资源
    最近更新 更多