如何将Xib自定义Cell的选中答案传递至ViewController判分
解决选择题测试程序的答案收集问题
嘿,我懂你的困扰——用自定义TableViewCell做选择题时,直接从Cell里取选中状态很容易因为复用出问题,咱们用数据模型+闭包回调的方式来搞定,这是iOS开发里处理这类问题的标准做法,稳得很!
第一步:创建问题数据模型
首先定义一个QuestionModel类,用来存储每个问题的内容、选项,以及用户选中的答案。这样每个问题的选中状态都和数据绑定,不会因为Cell复用丢失:
import UIKit class QuestionModel { let questionText: String let options: [String] var selectedAnswer: String? // 存储用户选中的答案,初始为nil init(questionText: String, options: [String]) { self.questionText = questionText self.options = options } }
第二步:修改自定义TableViewCell,添加选中回调
在你的自定义Cell类里,添加一个闭包属性,当用户点击选项按钮时,把选中的选项文本通过闭包传递给ViewController。同时调整按钮的点击事件,更新选中状态并触发回调:
import UIKit class ChoiceTableViewCell: UITableViewCell { @IBOutlet weak var questionLabel: UILabel! @IBOutlet weak var optionBtn1: UIButton! @IBOutlet weak var optionBtn2: UIButton! @IBOutlet weak var optionBtn3: UIButton! // 定义回调闭包,传递选中的选项文本 var didSelectOption: ((String) -> Void)? override func awakeFromNib() { super.awakeFromNib() // 给按钮添加点击事件(如果之前没加的话) optionBtn1.addTarget(self, action: #selector(optionTapped(_:)), for: .touchUpInside) optionBtn2.addTarget(self, action: #selector(optionTapped(_:)), for: .touchUpInside) optionBtn3.addTarget(self, action: #selector(optionTapped(_:)), for: .touchUpInside) } // 配置Cell数据,同时重置选中状态 func configure(with model: QuestionModel) { questionLabel.text = model.questionText optionBtn1.setTitle(model.options[0], for: .normal) optionBtn2.setTitle(model.options[1], for: .normal) optionBtn3.setTitle(model.options[2], for: .normal) // 根据模型里的选中状态更新按钮背景色 let selectedAnswer = model.selectedAnswer optionBtn1.backgroundColor = selectedAnswer == model.options[0] ? .systemBlue : .white optionBtn2.backgroundColor = selectedAnswer == model.options[1] ? .systemBlue : .white optionBtn3.backgroundColor = selectedAnswer == model.options[2] ? .systemBlue : .white } @objc private func optionTapped(_ sender: UIButton) { guard let selectedText = sender.titleLabel?.text else { return } // 更新当前Cell的按钮选中样式 optionBtn1.backgroundColor = selectedText == optionBtn1.titleLabel?.text ? .systemBlue : .white optionBtn2.backgroundColor = selectedText == optionBtn2.titleLabel?.text ? .systemBlue : .white optionBtn3.backgroundColor = selectedText == optionBtn3.titleLabel?.text ? .systemBlue : .white // 通过闭包把选中的文本传递给ViewController didSelectOption?(selectedText) } }
第三步:在ViewController里维护模型数组,处理回调
在ViewController中,创建一个questions: [QuestionModel]数组来存储所有问题数据,在TableView的数据源方法里配置Cell,并绑定闭包来更新模型的选中状态:
import UIKit class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { @IBOutlet weak var tableView: UITableView! // 存储所有问题的模型数组 private var questions: [QuestionModel] = [] override func viewDidLoad() { super.viewDidLoad() // 初始化数据(这里替换成你实际的问题数据) setupTestData() // 注册Xib Cell tableView.register(UINib(nibName: "ChoiceTableViewCell", bundle: nil), forCellReuseIdentifier: "ChoiceCell") tableView.dataSource = self tableView.delegate = self } private func setupTestData() { questions = [ QuestionModel(questionText: "1+1等于几?", options: ["1", "2", "3"]), QuestionModel(questionText: "iOS开发的主语言是?", options: ["Java", "Swift", "Python"]) ] } // MARK: - UITableView DataSource func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return questions.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "ChoiceCell", for: indexPath) as! ChoiceTableViewCell let model = questions[indexPath.row] cell.configure(with: model) // 绑定闭包,更新对应模型的选中答案 cell.didSelectOption = { [weak self] selectedText in guard let self = self else { return } self.questions[indexPath.row].selectedAnswer = selectedText } return cell } // Grade按钮的点击事件 @IBAction func gradeButtonTapped(_ sender: UIBarButtonItem) { // 收集所有用户选中的答案 let userAnswers = questions.compactMap { $0.selectedAnswer } // 这里就可以对userAnswers进行判分了,比如和正确答案数组对比 print("用户选中的答案:\(userAnswers)") } }
为什么要这么做?
因为TableView的Cell是复用机制,如果直接把选中状态存在Cell里,当Cell滚出屏幕再滚回来时,状态会丢失或者混乱。而把状态存在数据模型里,每个问题的选中状态都和数据绑定,不管Cell怎么复用,只要重新配置Cell时从模型取状态,就不会出错。
这样一来,点击Grade按钮时,直接遍历模型数组就能轻松拿到所有用户选中的答案,判分就简单啦!
内容的提问来源于stack exchange,提问作者ntf
相关产品推荐
相关产品推荐

