You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:52:48