如何解决在 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 行。
这只发生在滚动并且一个新对象被添加到数组之后。如果一个新对象被添加到数组并且用户没有滚动,它就可以完美地工作。如果没有新对象添加到数组并且用户滚动,它就可以完美运行。
下面是用户界面的快照。绿色是被点击的单元格,红色是正在重新加载的单元格:
解决方法
解决了问题。与我正在运行的检查函数有关,以查看其他用户是否更新了填充此表的数据库值——我没有意识到它在 didSelect 之后运行。我已经对上面评论中提到的代码进行了适当的编辑,并且它完全按预期工作。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。