Как обновить UITableView при повторном использовании UICell - PullRequest
0 голосов
/ 15 мая 2019

У меня есть UIViewController с UITableView внутри.В этой таблице у меня есть несколько строк, и у каждой строки есть несколько кнопок.Когда пользователь нажимает кнопку, значок кнопки изменяется.Мне удалось сохранить состояние кнопок в объекте, но у меня есть проблемы с ошибкой, которая заключается в случайном выборе других кнопок при проверке выбранной кнопки.Вот мой код:

// MODEL
class ChecklistItem: NSObject, NSCoding {

// Recorded values
    var vehiclePass = 0 // 0 = unchecked, 1 = pass, 2 = fail
    var trailerPass = 0 // 0 = unchecked, 1 = pass, 2 = fail
    var vehicleComment = String()
    var trailerComment = String()
}

 // Set the cell of UITableView.
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: Constants.checklistCell, for: indexPath) as! ChecklistCell

        let itemCategory = itemSections[indexPath.section]
        let item = itemCategory.checklistItems[indexPath.row]

        titleForSelectedQuestion = item.descript

        cell.delegate = self
        cell.configCell(item)

        // 0 = questions is not checked yet ( white icon ), 1 = question was checked as PASS ( green icon ), 2 = question was checked as FAIL ( red icon )
        if item.vehiclePass == 0 {
            // vehicle pass = white icon & vehicle fail = white icon
            cell.vehiclePassButton.setImage(UIImage(named: Constants.whiteTickIcon), for: UIControl.State.normal)
            cell.vehicleFailButton.setImage(UIImage(named: Constants.whiteCrossIcon), for: UIControl.State.normal)
        }
        if item.trailerPass == 0 {
            // trailer pass = white icon & trailer fail = white icon
            cell.trailerPassButton.setImage(UIImage(named: Constants.whiteTickIcon), for: UIControl.State.normal)
            cell.trailerFailButton.setImage(UIImage(named: Constants.whiteCrossIcon), for: UIControl.State.normal)
        }
        if item.vehiclePass == 1 {
            // vehicle pass = green icon & vehicle fail = white icon
            cell.vehiclePassButton.setImage(UIImage(named: Constants.greenTickIcon), for: UIControl.State.normal)
            cell.vehicleFailButton.setImage(UIImage(named: Constants.whiteCrossIcon), for: UIControl.State.normal)
        }
        if item.vehiclePass == 2 {
            // vehicle pass = white icon & vehicle fail = red icon
            cell.vehiclePassButton.setImage(UIImage(named: Constants.whiteTickIcon), for: UIControl.State.normal)
            cell.vehicleFailButton.setImage(UIImage(named: Constants.redCrossIcon), for: UIControl.State.normal)
        }

        if item.trailerPass == 1 {
            // trailer pass = green icon & trailer fail = white icon
            cell.trailerPassButton.setImage(UIImage(named: Constants.greenTickIcon), for: UIControl.State.normal)
            cell.trailerFailButton.setImage(UIImage(named: Constants.whiteCrossIcon), for: UIControl.State.normal)
        }
        if item.trailerPass == 2 {
            // trailer pass = white icon & trailer fail = red icon
            cell.trailerPassButton.setImage(UIImage(named: Constants.whiteTickIcon), for: UIControl.State.normal)
            cell.trailerFailButton.setImage(UIImage(named: Constants.redCrossIcon), for: UIControl.State.normal)
        }

        print("For section \(indexPath.section) row: \(indexPath.row) - vehicle status = \(item.vehiclePass)")
        print("For section \(indexPath.section) row: \(indexPath.row) - trailer status = \(item.trailerPass)")

 return cell
  }
}


extension ChecklistVC: ChecklistCellDelegate{

    // Check if user pressed Pass or Fail btn for Vehicle/Trailer and scroll to next question
    func tappedOnVehicleOrTrailerButtons(vehiclePassBtn: UIButton, vehicleFailBtn: UIButton, trailerPassBtn: UIButton, trailerFailBtn: UIButton, selectedCell: ChecklistCell) {

        let indexPath = questionsTableView.indexPath(for: selectedCell)
        let item = itemSections[indexPath?.section ?? 0].checklistItems[indexPath?.row ?? 0]

        if vehiclePassBtn.isSelected {
            item.vehiclePass = 1
        }
        if vehicleFailBtn.isSelected {
            item.vehiclePass = 2
        }
        if trailerPassBtn.isSelected {
            item.trailerPass = 1
        }
        if trailerFailBtn.isSelected {
            item.trailerPass = 2
        }
        displayChecksLeft()
        questionsTableView.reloadData()

        print("For section \(indexPath?.section ?? 0) row: \(indexPath?.row ?? 0) - vehicle status = \(item.vehiclePass)")
        print("For section \(indexPath?.section ?? 0) row: \(indexPath?.row ?? 0) - trailer status = \(item.trailerPass)")

        if (vehiclePassBtn.isSelected || vehicleFailBtn.isSelected) && (trailerPassBtn.isSelected || trailerFailBtn.isSelected) {
            displayChecksLeft()
            scrollDown()
        }
        if (vehicleFailBtn.isTouchInside || trailerFailBtn.isTouchInside) {
            self.lastIndexPath = indexPath
            self.performSegue(withIdentifier: Constants.goChecklistAddComment, sender: nil)
        }
    }
}

Вот код для ячейки:


protocol ChecklistCellDelegate {
    func tappedOnVehicleOrTrailerButtons(vehiclePassBtn: UIButton, vehicleFailBtn: UIButton, trailerPassBtn: UIButton, trailerFailBtn: UIButton, selectedCell: ChecklistCell)
    func tapGestureOnCell(_ selectedCell: ChecklistCell)
}

class ChecklistCell: UITableViewCell {

    // Interface Links
    @IBOutlet weak var questionName: UILabel!
    @IBOutlet weak var vehiclePassButton: UIButton!
    @IBOutlet weak var vehicleFailButton: UIButton!
    @IBOutlet weak var trailerPassButton: UIButton!
    @IBOutlet weak var trailerFailButton: UIButton!
    @IBOutlet weak var vehicleCommentLabel: UILabel!
    @IBOutlet weak var trailerCommentLabel: UILabel!
    @IBOutlet weak var tagIconImageView: UIImageView!
    @IBOutlet weak var tagNameLabel: UILabel!
    @IBOutlet weak var defectImageView: CustomImageView!

    // Constraints Links
    @IBOutlet weak var vehicleCommentHeightConstraint: NSLayoutConstraint!
    @IBOutlet weak var trailerCommentHeightConstraint: NSLayoutConstraint!
    @IBOutlet weak var tagIconHeightConstraint: NSLayoutConstraint!
    @IBOutlet weak var tagNameBottomConstraint: NSLayoutConstraint!
    @IBOutlet weak var defectImageHeightConstraint: NSLayoutConstraint!

    // Properties
    var delegate: ChecklistCellDelegate?

    override func awakeFromNib() {
        super.awakeFromNib()

        let longTapGesture = UILongPressGestureRecognizer(target: self, action: #selector(self.tapEdit(sender:)))
        addGestureRecognizer(longTapGesture)
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

    }

    // Detect when the user press Long Tap on any cell
    @objc func tapEdit(sender: UITapGestureRecognizer) {
        delegate?.tapGestureOnCell(self)
    }

    // Config the cell for Defect and Damage Check
    func configCell(_ checklistItem: ChecklistItem){

        questionName.text = checklistItem.descript
        defectImageView.image = UIImage(named: String(checklistItem.imagesPath?.last ?? String()))
        vehicleCommentLabel.text = checklistItem.vehicleComment
        trailerCommentLabel.text = checklistItem.trailerComment
        tagIconImageView.image = UIImage(named: Constants.tagIcon)
    }


    // Function to change the icon when the user press Pass or Fail Btn
    func changeIconOnBtnTap(checkedBtn: UIButton, uncheckedBtn: UIButton){
        if checkedBtn.isSelected == true {
            checkedBtn.isSelected = true // user can't uncheck the button
            uncheckedBtn.isSelected = false // the unchecked button is white now
        }else {
            checkedBtn.isSelected = true
            uncheckedBtn.isSelected = false
        }
    }

    // Check if the user press Pass or Fail btn for Vehicle or Trailer
    @IBAction func passOrFailBtnTapped(_ sender: UIButton) {

        sender.isSelected = true

        delegate?.tappedOnVehicleOrTrailerButtons(vehiclePassBtn: vehiclePassButton,
                                                  vehicleFailBtn: vehicleFailButton,
                                                  trailerPassBtn: trailerPassButton,
                                                  trailerFailBtn: trailerFailButton,
                                                  selectedCell: self)
    }
}

Вот захват с ошибкой:

enter image description here

Спасибо за прочтение.

Ответы [ 2 ]

1 голос
/ 16 мая 2019

Вот исправление, если кто-то хочет реализовать такую ​​же функциональность:

// Config the cell for Defect and Damage Check
func configCell(_ checklistItem: ChecklistItem){

    questionName.text = checklistItem.descript

    // Detect when user press Pass or Fail on any button and execute the assigned function to change the icon
    vehiclePassButton.addTarget(self, action: #selector(vehiclePassButtonTapped), for: UIControl.Event.touchUpInside)
    vehicleFailButton.addTarget(self, action: #selector(vehicleFailButtonTapped), for: UIControl.Event.touchUpInside)
    trailerPassButton.addTarget(self, action: #selector(trailerPassButtonTapped), for: UIControl.Event.touchUpInside)
    trailerFailButton.addTarget(self, action: #selector(trailerFailButtonTapped), for: UIControl.Event.touchUpInside)
}

@objc func vehiclePassButtonTapped(){
    changeIconOnBtnTap(checkedBtn: vehiclePassButton, uncheckedBtn: vehicleFailButton)
}

@objc func vehicleFailButtonTapped(){
    changeIconOnBtnTap(checkedBtn: vehicleFailButton, uncheckedBtn: vehiclePassButton)
}

@objc func trailerPassButtonTapped(){
    changeIconOnBtnTap(checkedBtn: trailerPassButton, uncheckedBtn: trailerFailButton)
}

@objc func trailerFailButtonTapped(){
    changeIconOnBtnTap(checkedBtn: trailerFailButton, uncheckedBtn: trailerPassButton)
}

// Function to change the icon when the user press Pass or Fail Btn
func changeIconOnBtnTap(checkedBtn: UIButton, uncheckedBtn: UIButton){
    if checkedBtn.isSelected{
        checkedBtn.isSelected = true // user can't uncheck the button
        uncheckedBtn.isSelected = false // the unchecked button is white now
    } else{
        checkedBtn.isSelected = false
    }
    checkedBtn.isSelected = false // reset button status
    uncheckedBtn.isSelected = false
}

Спасибо Sh_Khan за попытку помочь мне !!!

1 голос
/ 15 мая 2019

Проблема здесь tappedOnVehicleOrTrailerButtons

    if vehiclePassBtn.isSelected {
        item.vehiclePass = 1
    }
    if vehicleFailBtn.isSelected {
        item.vehiclePass = 2
    }
    if trailerPassBtn.isSelected {
        item.trailerPass = 1
    }
    if trailerFailBtn.isSelected {
        item.trailerPass = 2
    }

Вы полностью зависите от свойства кнопок isSelected, состояние которого может быть отменено для изменения значений модели, но вы должны проверить текущее значение модели и действовать соответственно


Так как вы отправляете этот параметр , selectedCell: ChecklistCell используйте его как другой метод

 let indexPath = tableView.indexPath(for:cell)!
 let itemCategory = itemSections[indexPath.section]
 let item = itemCategory.checklistItems[indexPath.row]
 // then check the value in item and go on

Другое дело, не перезагружайте всю таблицу здесь

questionsTableView.reloadData()

но только затронутый indexPath

questionsTableView.reloadRows([indexPath],for:.none)

и поместите его в конец функции

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...