问题
I've a survey with 8 questions and each question has a picker view with options loading from the server. This is in the UI Collection View. The survey works fine upto 5 questions but when we added more than 5, whatever the option we pick for the question 1 gets selected both for question1 and 6. same with question 2 and 3 which returns Index out of range error and I see only 5 answers instead of 8. Any help is appreciated.
Gif file of the CollectionView
Errors Screen shot
Here is my code:
class QuestionCollectionViewController: UICollectionViewController {
// Mark: - Properties
let reuseIdentifier = "QuestionCell"
let survey: Survey? = UserDefaults.getCodable(.survey)
// number of cells is based on the
override func collectionView(_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return survey?.questions.count ?? 0
}
override func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier,
for: indexPath) as! QuestionViewCell
let data = survey?.questions[indexPath.item]
cell.questionResponseTF.delegate = self
cell.questionResponseTF.tag = indexPath.item
cell.questionResponseTF.text = data.selectedValue
}
func textFieldDidBeginEditing(_ textField: UITextField) {
let index = IndexPath(item: textField.tag, section: 0)
constructQuestionViewCell(cell,withQuestion:survey?.questions[index.item])
}
// MARK: - Helpers
/// populates the QuestionViewCell with SurveyQuestion and style ui elements
private func constructQuestionViewCell(_ cell: QuestionViewCell, withQuestion question: SurveyQuestion? = nil) {
cell.questionTitle.text = question?.title
cell.questionTitle.numberOfLines = 0
cell.questionTitle.sizeToFit()
// cell.questionDescription.text = question?.description
// cell.questionDescription.sizeToFit()
cell.questionResponse.frame.origin.y = cell.questionTitle.frame.maxY + 7
cell.questionResponse.inputAccessoryView = doneToolbar()
cell.questionResponse.layer.borderColor = UIColor.lightGray.cgColor
cell.questionResponse.layer.borderWidth = 1.0
cell.questionResponse.layer.cornerRadius = 5.0
// TODO refactor and remove else if keying off of "ratepain" once survey questions have been updated in the api
if (question?.type == "number_list") {
let options = question?.values ?? [" ", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
let picker = CustomPickerView(frame: .zero, textView: cell.questionResponse, options: options)
cell.questionResponse.inputView = picker
picker.reloadAllComponents()
}
else if (question?.key == "ratepain") {
let options = [" ", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
let picker = CustomPickerView(frame: .zero, textView: cell.questionResponse, options: options)
cell.questionResponse.inputView = picker
}
cell.sizeToFit()
}
回答1:
you need to add a extra data into model as selected value then set that value to textfield when selecting picker view
class QuestionCollectionViewController: UICollectionViewController,UITextFieldDelegate {
// Mark: - Properties
let reuseIdentifier = "QuestionCell"
let survey: Survey? = UserDefaults.getCodable(.survey)
// number of cells is based on the
override func collectionView(_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return survey?.questions.count ?? 0
}
override func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier,
for: indexPath) as! QuestionViewCell
let data = survey?.questions[indexPath.item]
cell.questionResponse.delegate = self
cell.questionResponse.tag = indexPath.item
cell.questionResponse.text = data.selectedValue
return cell
}
func textFieldDidBeginEditing(_ textField: UITextField) {
let index = IndexPath(item: textField.tag, section: 0)
constructQuestionViewCell(cell,withQuestion:survey?.questions[index.item])
}
private func constructQuestionViewCell(_ cell: QuestionViewCell, withQuestion question: SurveyQuestion? = nil) {
cell.questionTitle.text = question?.title
cell.questionTitle.numberOfLines = 0
cell.questionTitle.sizeToFit()
cell.questionResponse.frame.origin.y = cell.questionTitle.frame.maxY + 7
cell.questionResponse.inputAccessoryView = doneToolbar()
cell.questionResponse.layer.borderColor = UIColor.lightGray.cgColor
cell.questionResponse.layer.borderWidth = 1.0
cell.questionResponse.layer.cornerRadius = 5.0
// TODO refactor and remove else if keying off of "ratepain" once survey questions have been updated in the api
if (question?.type == "number_list") {
let options = question?.values ?? [" ", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
let picker = CustomPickerView(frame: .zero, textView: cell.questionResponse, options: options)
//cell.questionResponse.inputView = picker
question?.selectedValue = picker.value
picker.reloadAllComponents()
}
else if (question?.key == "ratepain") {
let options = [" ", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
let picker = CustomPickerView(frame: .zero, textView: cell.questionResponse, options: options)
//cell.questionResponse.inputView = picker
question?.selectedValue = picker.value
}
cell.sizeToFit()
}
回答2:
I see multiple issues here.
- The cell you were passing to
constructQuestionViewCell
method is not you are returning. Either you need to pass the cell with address or better return the cell from the function and pass it tocellForItemAt
.
override func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier,
for: indexPath) as! QuestionViewCell
return constructQuestionViewCell(cell, withQuestion: survey?.questions[indexPath.item])
}
private func constructQuestionViewCell(_ cell: QuestionViewCell, withQuestion question: SurveyQuestion? = nil) -> QuestionViewCell {
cell.questionTitle.text = question?.title
cell.questionTitle.numberOfLines = 0
cell.questionTitle.sizeToFit()
if (question?.type == "number_list") {
let options = question?.values ?? [" ", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
let picker = CustomPickerView(frame: .zero, textView: cell.questionResponse, options: options)
cell.questionResponse.inputView = picker
picker.reloadAllComponents()
}
return cell
}
- Also, if question type is not equal to "number_list" you are not updating the options, as the cell is being reused, it will holding the old value.
来源:https://stackoverflow.com/questions/59040165/option-selected-from-one-of-the-picker-view-duplicates-in-another-picker-view-sw