Maysara Odeh
Maysara Odeh

Reputation: 11

Cell Reusing in UITableView

class ViewController: UIViewController , UITableViewDelegate , UITableViewDataSource{
    @IBOutlet weak var tableView: UITableView!

    var questions:[Question] = []
    var sectionCountGlobal = 0
    override func viewDidLoad() {
        super.viewDidLoad()

        questions = fillQuestions()
    }

    func fillQuestions()-> [Question]{
        var temp : [Question] = []
        var choices : [Choice] = []
        let choice = Choice(id: 1, text: "choice ", status: 1, questionId: 1)
        choices.append(choice)
        choices.append(choice)
        choices.append(choice)
        choices.append(choice)
        choices.append(choice)
        choices.append(choice)

        let q1 = Question(id: 1, text: "Ahmad 55 years old man with a history of hypertension and hypocholesteremia was in a wedding and during the party he starts to feel chest pain and dizzy, his wife brought him to the emergency department. The ER nurse checked his vital signs: BP 88/50, HR: 45, RR:10, SPaO2: 90% and O2 per nasal cannula was started at 4l/minute. Few seconds later Mr.Ahmad lost consciousness and the code blue team were activated.", choices: choices)
        let q2 = Question(id: 1, text: "question 2", choices: choices)
        let q3 = Question(id: 1, text: "question 3", choices: choices)

        temp.append(q1)
        temp.append(q2)
        temp.append(q3)
        return temp
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return questions.count
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        sectionCountGlobal = section
        return questions[section].choices.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if indexPath.row == 0{
            let questionTextCell = tableView.dequeueReusableCell(withIdentifier: "QuestionTextCell") as! QuestionTextCell
            questionTextCell.setQuestionText(text: questions[indexPath.section].text)
            return questionTextCell
        }else{
            let choiceCell = tableView.dequeueReusableCell(withIdentifier: "ChoiceCell") as! ChoiceCell
            choiceCell.choiceText.text = questions[indexPath.section].choices[indexPath.row].text
            return choiceCell
        }
    }

    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 50
    }

    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        let questionNumber = "Q" + String(section+1)
        return questionNumber
    }

    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        return 3
    }

    override func viewWillAppear(_ animated: Bool) {
       tableView.estimatedRowHeight = 100
        tableView.rowHeight = UITableViewAutomaticDimension
    }
}

I am working on a quiz app and there is multiple choices for each question so when checking the radio button in a cell and scroll to other cells i found that the other cells got checked without touching them what is the solution.

I tried different cell reusing methods also prepareForReuse() and nothing works how can i treat each cell independently without affect from other cells , i don't know the number of questions it is come from server.

question1 i checked the first choice

question3 the choice checked by itself

Upvotes: 1

Views: 92

Answers (2)

Anup Kanjariya
Anup Kanjariya

Reputation: 302

The issue in you code is you not changing the status of your radio button. When you select the option from didSelectRowAt method, you have to change the status of your choice. As per your choice model you can change the status of particular choice status. Following are both method that can manage your selection of choice(your status variable should be Bool type):

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if indexPath.row == 0{
        let questionTextCell = tableView.dequeueReusableCell(withIdentifier: "QuestionTextCell") as! QuestionTextCell
        questionTextCell.setQuestionText(text: questions[indexPath.section].text)
        return questionTextCell
    }else{
        let choiceCell = tableView.dequeueReusableCell(withIdentifier: "ChoiceCell") as! ChoiceCell

        // update your radio button UI
        choiceCell.radioButton.isSelected = questions[indexPath.section].choices[indexPath.row].status

        choiceCell.choiceText.text = questions[indexPath.section].choices[indexPath.row].text
        return choiceCell
    }
}



func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    questions[indexPath.section].choices[indexPath.row].status = !questions[indexPath.section].choices[indexPath.row].status
    tableView.reloadData()

}

Upvotes: 0

Milan Nosáľ
Milan Nosáľ

Reputation: 19767

In your cellForRowAt implementation you have to reset the cell's state according to whether it is selected or not. Due to cell reuse, you can get a cell which was previously selected, but now should not be selected - in that case you have to tell the cell to get unselected (and vice versa):

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    if indexPath.row == 0{
        let questionTextCell = tableView.dequeueReusableCell(withIdentifier: "QuestionTextCell") as! QuestionTextCell
        questionTextCell.setQuestionText(text: questions[indexPath.section].text)
        return questionTextCell
    } else {
        let choiceCell = tableView.dequeueReusableCell(withIdentifier: "ChoiceCell") as! ChoiceCell

        // here detect if the cell should be selected and set it accordingly, so something like:
        let isSelected = isSelectedChoice(questions[indexPath.section].choices[indexPath.row])
        choiceCell.isSelected = isSelected
        // of course this is just a mockup, since I don't know exactly how you manage selection,
        // but it should get you on the right path

        choiceCell.choiceText.text = questions[indexPath.section].choices[indexPath.row].text
        return choiceCell
    }
}

Upvotes: 1

Related Questions