Swift: Last cell in tableView gets userInteraction disabled when it shouldn't

318 views Asked by At

I have a tableview with two sections and I want the user interaction of the textView inside the cells of the second section to be disabled (those are completed, users are not meant to be able to edit their text). And the code below from cellForRowAt works fine, but when I add a new cell (which gets added to the end of section 0, this somehow ends up having userInteraction disabled, and I can't figure out why. Reloading the viewController (closing the page and opening it again) seems to fix the problem.

Any ideas or thoughts on why this might be happening? Thanks in advance.

If any further details are needed, I'm happy to share them.

Here is the code from cellForRow

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "ActionCell", for: indexPath) as! StepCell

    if indexPath.section == 0 {
        cell.label.alpha = 1

        // This code is needed to remove the strikethrough from this cell
        let attr = NSMutableAttributedString(attributedString: (cell.label.attributedText)!)
        let originalRange = NSMakeRange(0, attr.length)
        attr.setAttributes([:], range: originalRange)
        cell.label.attributedText = attr
        cell.label.attributedText = NSMutableAttributedString(string: "", attributes: [:])

        cell.label.text = goals[selectedCell].steps![indexPath.row].title
        cell.checkbox.image = UIImage(named: "unticked")
        cell.focus.isHidden = false
    } else {
        cell.label.alpha = 0.5
        cell.label.attributedText = goals[selectedCell].completedSteps![indexPath.row].title.withStrikethroughStyle(.single)
        cell.checkbox.image = UIImage(named: "ticked")
        cell.focus.isHidden = true
        cell.label.isUserInteractionEnabled = false
    }

    cell.label.textContainerInset = UIEdgeInsets(top: 20, left: -6, bottom: 20, right: 0);
    cell.label.textColor = .white
    cell.label.tintColor = UIColor(named: "Yellow")
    cell.label.keyboardAppearance = .dark
    cell.label.font = UIFont.boldSystemFont(ofSize: 18)
    cell.label.disableKeyboardAccessory()

    cell.label.delegate = self
    cell.delegate = self

    print("For \(indexPath) user intercation enabled is \(cell.label.isUserInteractionEnabled)")

    return cell

}

And here is the code for the action to add a new cell

@IBAction func plusTU(_ sender: Any) {

    goals[selectedCell].steps?.append(Step(title: ""))

    let numberOfCells = tableview.numberOfRows(inSection: 0)

    tableview.reloadData()
    tableview.layoutIfNeeded()

    DispatchQueue.main.asyncAfter(deadline: .now()+0.2) {
        let cell = self.tableview.cellForRow(at: IndexPath.init(row: numberOfCells, section: 0)) as? StepCell
        cell?.label.becomeFirstResponder()
    }

    let indexPath = IndexPath(row: goals[selectedCell].steps!.count - 1, section: 0)
    tableview.scrollToRow(at: indexPath, at: .bottom, animated: true)

    progressBar.configure(goalsIndex: selectedCell)
    configureCompleteGoalButton(buttonHeight: completeGoalButtonHeight, progressBarHeight: progressBarHeight, progressBar: progressBar)
}

If it's relevant, I have a textView delegate that looks like this:

extension GoalDetails: UITextViewDelegate {


func textViewDidChange(_ textView: UITextView) {
    let cell = textView.superview?.superview as? StepCell
    let indexPath = tableview.indexPath(for: cell!)
    goals[selectedCell].steps![indexPath!.row].title = textView.text
    resizeTableViewCell()
}

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if text == "\n" || text == "\t" {
        textView.resignFirstResponder()
        return false
    }
    return true
}

func textViewDidEndEditing(_ textView: UITextView) {
    writeJSONGoals()
}

func textViewDidBeginEditing(_ textView: UITextView) {

    if descriptionExists == true {
        descriptionHeight.isActive = true
        descriptionExpanded = false
    }

}
}

and that function it's calling is this:

func resizeTableViewCell(){
    tableview.beginUpdates()
    tableview.endUpdates()
    tableview.layoutIfNeeded()
}

The page looks like this and I'm also attaching a print from the console from cellForRow enter image description hereenter image description here

1

There are 1 answers

4
vacawama On BEST ANSWER

Cells get reused. You need to make sure to explicitly set isUserInteractionEnabled to the appropriate value for all cells to make sure they're not using a stale value.

For cells of section 0, you need to set:

cell.label.isUserInteractionEnabled = true