[英]How to refresh UITableView when UICell is reused
我有一個帶有UITableView
的UIViewController
。 在該表中,我只有幾行,每行都有幾個按鈕。 當用戶單擊按鈕時,按鈕的圖標將更改。 我設法將按鈕的狀態保存在一個對象中,但是我遇到了一個錯誤,即當我檢查所選按鈕時會隨機選擇其他按鈕。 這是我的代碼:
// 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)
}
}
這是該錯誤的捕獲:
感謝您閱讀本文。
問題在這里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)
並將其放在函數末尾
如果有人要實現相同的功能,請執行以下修復程序:
// 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嘗試幫助我!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.