我知道有很多与我的问题类似的问题,但是其中许多已经过时,还有其他问题与我的案子无关。
我在UITableView
中有一个问卷,其中包含5个问题,每个问题有3个选择。
选择是一个UIButton,单击后可更改图像。
但是,当第一个问题得到回答时,第五个问题也将得到回答!
这是我的tableView
方法:
var questions: [Question] = []
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return questions.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let question = questions[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "choicesCell") as! ChoicesCell
cell.setQuestion(question: question)
cell.selectionStyle = .none
return cell
}
这是在选择按钮时将图像设置到选择按钮的方式:
@IBAction func answerOneTapped(_ sender: UIButton) {
delegate?.didTapAnswerOne()
print("answerOneTapped")
answerOneButton.setImage(#imageLiteral(resourceName: "ElipseSelected"), for: .normal)
answerTwoButton.setImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
answerThreeButton.setImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
}
@IBAction func answerTwoTapped(_ sender: UIButton) {
delegate?.didTapAnswerTwo()
print("answerTwoTapped")
answerOneButton.setImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
answerTwoButton.setImage(#imageLiteral(resourceName: "ElipseSelected"), for: .normal)
answerThreeButton.setImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
}
@IBAction func answerThreeTapped(_ sender: UIButton) {
delegate?.didTapAnswerThree()
print("answerThreeTapped")
answerOneButton.setImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
answerTwoButton.setImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
answerThreeButton.setImage(#imageLiteral(resourceName: "ElipseSelected"), for: .normal)
}
我尝试了几种没有运气的解决方案,例如:
questions.removeAll()
在cellForRowAt
和ViewWillAppear
我还尝试将按钮设置为以下未选择的选项:
override func prepareForReuse() {
super.prepareForReuse()
answerOneButton.setImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
answerTwoButton.setImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
answerThreeButton.setImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
}
我已经花了很多时间尝试解决这个问题。并且我阅读了有关dequeueReusableCell
的Apple文档,并收集了许多信息,但没有结果...请任何人帮助!
答案 0 :(得分:2)
问题在于,即使prepareForReuse可以正常工作(奇怪的是,它没有工作),当您不需要它时,它也会重用您的第一个单元格。 我一直使用的最佳解决方案是将单元格状态保存在委托中,并在tableView(_:cellForRowAt :)中重置它们
例如:
在您的情况下,您可以将3个案例添加到Question类属性selecteddAnswer并枚举
set JPDA_OPTS=-agentlib:jdwp=transport=dt_socket,address=8082,server=y,suspend=n
在您的cell.setQuestion(question :)函数更新按钮的图像中。像这样的东西:
enum answer {
case one
case two
case three
}
var choosedAnswer: answer?
并且不要忘记在选择按钮后更新[问题]数组中的模型
switch question.choosedAnswer {
case .one:
answerOneButton.setImage(#imageLiteral(resourceName: "ElipseSelected"), for: .normal)
answerTwoButton.setImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
answerThreeButton.setImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
case .two:
answerOneButton.setImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
answerTwoButton.setImage(#imageLiteral(resourceName: "ElipseSelected"), for: .normal)
answerThreeButton.setImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
case .three:
answerOneButton.setImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
answerTwoButton.setImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
answerThreeButton.setImage(#imageLiteral(resourceName: "ElipseSelected"), for: .normal)
default:
answerOneButton.setImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
answerTwoButton.setImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
answerThreeButton.setImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
}
在您的单元格委托中,点击功能发送自我:
func didTapAnswerOne(cell: UITableViewCell) {
guard let indexPath = tableView.indexPath(for: sender) else {return}
questions[indexPath.row] = questions[indexPath.row] == .one ? nil : .one
}
func didTapAnswerTwo(cell: UITableViewCell) {
guard let indexPath = tableView.indexPath(for: sender) else {return}
questions[indexPath.row] = questions[indexPath.row] == .two ? nil : .two
}
func didTapAnswerThree(cell: UITableViewCell) {
guard let indexPath = tableView.indexPath(for: sender) else {return}
questions[indexPath.row] = questions[indexPath.row] == .three ? nil : .three
}
答案 1 :(得分:0)
具有tableView实例的UIViewController
应该知道所有已更改的状态。
类似这样的事情。您可以创建对象来实现类似的目的
[Question 1] --> [State of Answer1, state of Answer2, state of Answer3]
[Question 2] --> [State of Answer1, state of Answer2, state of Answer3]
[Question 3] --> [State of Answer1, state of Answer2, state of Answer3]
so forth..
Question 1 -> (False, False, False)
如果用户单击问题1的答案2,则:
Question 1 -> (False, True, False)
然后在cellForItem
中
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
.
.
(question[index.row].isTapped[answer])?
cell.answerOneButtonsetImage(#imageLiteral(resourceName: "ElipseSelected"), for: .normal)
:cell.answerOneButtonsetImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
.
}
答案 2 :(得分:0)
从Apple documentation prepareForReuse()
...
出于性能原因,您应该仅重置单元格的属性 与内容无关的内容,例如Alpha,编辑和 选择状态。表格视图的委托在 tableView(_:cellForRowAt :)应该始终在重置所有内容时 重用单元格。如果单元格对象没有关联的重用 标识符,则不会调用此方法。
此摘录中最重要的一点...
tableView(_:cellForRowAt:)
中的表视图的委托在重用单元格时应始终重置所有内容。
我的建议是重置tableView(_:cellForRowAt:)
中的内容。
例如...
cell.answerOneButton.setImage(UIImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
cell.answerTwoButton.setImage(UIImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
cell.answerThreeButton.setImage(UIImage(#imageLiteral(resourceName: "Elipse"), for: .normal)
请原谅我,虽然这听起来是居高临下的(不是故意的),但它将有助于将模型和视图视为独立的。视图不知道模型的(选择)状态,并且模型不管理视图。表格视图控制器是两者之间的通信器(控制器)。
因此,也许第五个单元格未更改模型中第五个问题的答案,而是视图仅根据控制器中的代码指令更改了其在屏幕上的显示。在加载和/或重新加载表视图时,可能值得使用断点和/或到终端的print()
检查模型值。
答案 3 :(得分:-1)
尝试与dequeueReusableCell(withIdentifier:for:)
https://developer.apple.com/documentation/uikit/uitableview/1614878-dequeuereusablecell一起使用出队
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let question = questions[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "choicesCell", for: indexPath) as! ChoicesCell
cell.setQuestion(question: question)
cell.selectionStyle = .none
return cell
}