微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 TableView 中调用 DidSelect 方法后,错误的单元格被重新加载/重用 [Swift]

如何解决在 TableView 中调用 DidSelect 方法后,错误的单元格被重新加载/重用 [Swift]

好的,我已经研究了 14 个小时,但仍然无法解决这个问题。

一个新对象被添加到数组并且用户已经滚动时,问题出现了,DidSelect 方法仍然按预期工作,但是一旦该方法完成,就会调用 cellForRowAt 方法(不明白为什么)并重新加载错误的单元格。这是我的 cellForRowAt 省略了无关紧要的代码

func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "doghouseCell",for: indexPath) as! DoghouseTableViewCell
    
    // Reset for dequeue
    cell.actTimeButton.isEnabled = false
    cell.addNoteLabel.isHidden = true
    cell.addNoteTextView.isHidden = true
    cell.cancelButton.isHidden = true
    cell.doneButton.isHidden = true
    cell.buttonStackView.isHidden = true
    cell.noteStackView.isHidden = true
    cell.editButton.isHidden = true
    cell.actTimeButton.borderColor = UIColor.clear
    
    // Hide skeleton if all data is received
    if allDataReceived == true || firstLoginToday == true {
        cell.hideAnimation()
    }
    
    if indexPath.section == 0 {
        // Get routine for this row
        let routine = routines[indexPath.row]
        print("CellFor Routine is \(routine.actTitle) at IndexPath: \(indexPath.row). Complete? \(routine.comp)")
        let timeConverted = Utilities.convert24to12(inString: routine.time)
        
        if routine.Aid.contains("custom") {
            cell.editButton.isEnabled = true
            cell.editButton.backgroundColor = .systemteal
        } else {
            cell.editButton.isEnabled = false
            cell.editButton.backgroundColor = .systemGray4
        }
        
        if indexPath.row == longPressIndex {
            
            // Set the time,title & desc.
            //OMITTED
               
            return cell
            
        } else {
            
            // Set the time,title & desc.
            cell.actTitle?.text = routine.actTitle
            cell.actDescription?.text = routine.actDescription
            
            if routine.comp == true {
                for routine in self.routines {
                    print("CELLFOR \(routine.Aid) \(routine.actTitle) \(routine.comp)")
                }
                print("routine \(routine.actTitle) is complete at indexPath: \(indexPath.row)")
                tableView.selectRow(at: indexPath,animated: true,scrollPosition: .none)
                cell.checkedImage.image = UIImage(named: "checkmark")
                cell.actTitle.textColor = #colorLiteral
                cell.actDescription.textColor = #colorLiteral
                // For hiding the title on the button when data is not yet received
                if allDataReceived == true || firstLoginToday == true {
                    cell.actTimeButton.setTitleColor(#colorLiteral)
                    cell.actTimeButton.setTitle(timeConverted,for: .normal)
                } else {
                    cell.actTimeButton.setTitle("",for: .normal)
                }
            } else {
                tableView.deselectRow(at: indexPath,animated: true)
                cell.checkedImage.image = UIImage(named: "unchecked")
                cell.actTitle.textColor = UIColor.darkGray
                cell.actDescription.textColor = UIColor.darkGray
                // For hiding the title on the button when data is not yet received
                if allDataReceived == true || firstLoginToday == true {
                    cell.actTimeButton.setTitleColor(.darkGray,for: .normal)
                    cell.actTimeButton.setTitle("⏱\(timeConverted)",for: .normal)
                }
            }
            
            return cell
        }
        
    } else {
    // Section 2 - Wrap Up
        
      return cell
    }
    
} 

这是我的 DidSelect 方法,它按预期工作,同样有遗漏。我还使用了 deselect 方法,它可以按预期单独工作,并且基本上与 didSelect 正好相反:

func tableView(_ tableView: UITableView,didSelectRowAt indexPath: IndexPath) {
    let cell = self.tableView.cellForRow(at: indexPath) as! DoghouseTableViewCell

    selectedRow = indexPath.row
    haptic.notificationOccurred(.success)
    
    if indexPath.section == 0 {
    
        // Get routine for this row
        let routine = routines[indexPath.row]
        let timeConverted = Utilities.convert24to12(inString: routine.time)
        print("Selected Routine is \(routine.actTitle) at IndexPath: \(indexPath.row)")
        
        if routine.comp == false {
            routine.comp = true
            // EDIT REMOVED tableView.selectRow(at: indexPath,scrollPosition: .none)
            // EDIT REMOVED cell.checkedImage.image = UIImage(named: "checkmark")
            // EDIT REMOVED cell.actTitle.textColor = #colorLiteral(red: 0.195538193,green: 0.7439816594,blue: 0.6510779262,alpha: 1)
            // EDIT REMOVED cell.actDescription.textColor = #colorLiteral
            // EDIT REMOVED cell.actTimeButton.setTitleColor(#colorLiteral)
            // EDIT REMOVED cell.actTimeButton.setTitle(timeConverted,for: .normal)
            print("Selected \(routine.actTitle) Routine is complete? \(routine.comp) at IndexPath: \(indexPath.row)")
            for routine in self.routines {
                print("DIDSELECT \(routine.Aid) \(routine.actTitle) \(routine.comp)")
            }
            
        } else {
            // routine.comp is false (shouldn't happen here)
        }
        print("DidSelect Complete")
        
    } else {
        // Section 2 - Wrap Up
    }
}

使用数组对象中的布尔值将数组从 didSelect 方法更新为 setSelected。这是用户选择第 5 行期间的快照,然后是 cellForRowAt 运行之后的快照(同样,不知道为什么):

| DidSelect | CellForRowAt (after DidSelect) | 
| --------- | ------- | 
| Value0 routine.comp = False     | Value0 routine.comp = False   | 
| Value1 routine.comp = False     | Value1 routine.comp = False   | 
| Value2 routine.comp = False     | Value2 routine.comp = False   | 
| Value3 routine.comp = False     | Value3 routine.comp = False   | 
| Value4 routine.comp = False     | ***Value4 routine.comp = True*** X   | 
| Value5 routine.comp = True      | Value5 routine.comp = True    | 
| Value6 routine.comp = False     | Value6 routine.comp = False   | 
| Value7 routine.comp = False     | Value7 routine.comp = False   |

我认为问题是添加/删除新值时 didSelect 和 cellForRow 之间的数组存在差异,但它们都包含相同的对象。

问题是,当点击第 5 行时,didSelect 会正确更新数组及其对象(一切都很好!),但随后调用了 cellForRowAt 并更新了错误的行(第 4 行)。

如果添加两个新对象并点击第 5 行,cellForRow 将更新第 3 行。

这只发生在滚动并且一个新对象被添加到数组之后。如果一个新对象被添加到数组并且用户没有滚动,它就可以完美地工作。如果没有新对象添加到数组并且用户滚动,它就可以完美运行。

下面是用户界面的快照。绿色是被点击的单元格,红色是正在重新加载的单元格:

Snapshot

解决方法

解决了问题。与我正在运行的检查函数有关,以查看其他用户是否更新了填充此表的数据库值——我没有意识到它在 didSelect 之后运行。我已经对上面评论中提到的代码进行了适当的编辑,并且它完全按预期工作。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。