0

I have a "point allocation" screen where you can either add points to yourself or subtract them from your enemy. You get this displayed at the end of your turn based on how many points you made. Here's the code that presents the allocation screen:

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.minusBtn.isEnabled = false
        cell.plusBtn.isEnabled = false
        if indexPath.row == 0 {
            cell.isSelf = true
        }
        cell.updatedButtons()
        return cell
    }

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
        return CGSize(width: 130, height: 130);
    }
}

Then this is the code for each cell in the collection view:

   @IBAction func plusTapped(_ sender: Any) {
        if isSelf {
            ptsUsed += 1
            ptsRemaining = cellDelegate?.pointUsed()
            updatedButtons()
        } else {
            ptsUsed -= 1
            ptsRemaining = cellDelegate?.pointReturned()
            updatedButtons()
        }
        pointLabel.text = String(ptsUsed)
        cellDelegate?.updateCellScores(index: cellIndex!, score: ptsUsed)
        cellDelegate?.updateCollection()
    }

    @IBAction func minusTapped(_ sender: Any) {
        if isSelf {
            ptsUsed -= 1
            ptsRemaining = cellDelegate?.pointReturned()
            updatedButtons()
        } else {
            ptsUsed += 1
            ptsRemaining = (cellDelegate?.pointUsed())!
            updatedButtons()
        }
        pointLabel.text = String(ptsUsed)
        cellDelegate?.updateCellScores(index: cellIndex!, score: ptsUsed)
        cellDelegate?.updateCollection()
    }

    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
        }
    }

and finally the delegate methods:

extension PointAllocVC: PointsAllocDelegate {
    func pointUsed() -> Int {
        pointsToAllocate -= 1
        return pointsToAllocate
    }

    func pointReturned() -> Int {
        pointsToAllocate += 1
        return pointsToAllocate
    }

    func updateCellScores(index: Int, score: Int) {
        if index != 0 {
            pointsUsedInCells[index] = -score
        } else {
            pointsUsedInCells[index] = score
        }
    }

    func updateCollection() {
        playerCollectionView.reloadData()
        reloadLabels()
    }
}

Anyways, the problem is that I get a really weird behavior ONLY in the following scenario (which is too common):

Say you have X points to allocate. Your only options are the plus button on yourself or the minus button on your opponent (at this point it works).
Now say you add X points to yourself. You have 0 points left and the plus button on YOUR side is disabled (as it should). However the opponent's "CELL" didnt update even though I called for the whole collection to update. If you play around with it you suddenly now have -x points to allocate (which shouldn't be possible). And then if you keep playing around it completely disables the opponents cell, no longer can you do anything to it. Here's a video to show the behavior: https://youtu.be/SPGxzL7ESwc

dvd.Void
  • 339
  • 1
  • 5
  • 21
  • In your cellForItemAtIndexPath you don't initialise `ptsRemaining` or `ptsUsed`, so how is `updatedButtons` supposed to know what to do? Your logic and data model is split between your cells and the view controller. You have the right idea about using a delegate, but I would have the button taps themselves simply notify the view controller that the plus or minus button was tapped in a cell and then let the view controller deal with the implications of that. This way your data model stays within your view controller and your cells don't need to know their index path (icky) – Paulw11 Jan 29 '18 at 10:15
  • thank you! I took out all the logic out of the cells and just basically called the delegate plus or minus with a `plustapped(cellIndex: Int)`. I don't see how I could do it without knowing the index of the cells tho. – dvd.Void Jan 29 '18 at 18:10
  • Have the cell pass `self` to the delegate. Then your delegate can ask the collectionview for the index path of the cell. See [this](https://stackoverflow.com/questions/28659845/swift-how-to-get-the-indexpath-row-when-a-button-in-a-cell-is-tapped/38941510#38941510) for a similar answer for tableviews. – Paulw11 Jan 29 '18 at 20:19
  • This is how I'm handling it as of now. However, now I got new issues :( https://stackoverflow.com/questions/48526280/what-exactly-is-the-indexpath-of-a-uicollection – dvd.Void Jan 30 '18 at 16:37

0 Answers0