Вы не правильно объявили функцию numberOfRowsInSection
; section
- это Int
, а не IndexPath
. В результате вы не реализовали обязательные функции UITableViewDataSource
.
Вы хотите:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return questionViewModel.numberOfRowsIn(section: section)
}
При соответствующем изменении модели вашего вида:
func numberOfRowsIn(section:Int) -> Int {
return self.questionsModelArray?[section].optionsModelArray.count ?? 0
}
Я бы также предложил вам пересмотреть использование неявно развернутых опций и принудительное развертывание; это просто запрос на сбои.
Например, нет никакой причины для свойства question
QuestionListModel
быть String!
; просто объявите его как String
и отключите инициализатор. А еще лучше: используйте Codable
, чтобы создать свою модель из JSON и избавиться от всего этого кода.
Вы также можете устранить развертывание силы в numberOfSections
:
func numberOfSections() -> Int {
return self.questionsModelArray?.count ?? 0
}
Я бы также предложил вам сделать QuestionListModel
структурой, а не NSObject
подклассом.
На вашем месте я бы рефакторировал, чтобы удалить модель представления, в этом случае она добавляет ненужную сложность, и для десериализации JSON используйте Codable
:
struct Questions: Codable {
enum CodingKeys: String, CodingKey {
case questions = "data"
}
var questions: [Question]
}
struct Question: Codable {
var question: String
var options: [String]
}
Ваш контроллер представления становится намного проще:
class ViewController: UIViewController, UITableViewDatasource {
var questionData: Questions?
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UINib(nibName: "NH_questionheader", bundle: nil), forCellReuseIdentifier: "HeaderCell")
tableView.register(UINib(nibName: "CellTableViewCell", bundle: nil), forCellReuseIdentifier: "Cell")
// You don't show how you load your JSON, but assuming you have it in an instance of `Data` called `jsonData`:
do {
self.questionData = try JSONDecoder().decode(Questions.self, from: jsonData)
} catch {
print("Error decoding JSON: \(error.localizedDescription)")
}
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: IndexPath) -> UIView? {
let identifier = "HeaderCell"
guard let questionData = self.questionData,
let headercell = tableView.dequeueReusableCell(withIdentifier: identifier) as? NH_questionheader else {
return nil
}
headercell.label.text = questionData.questions[section].question
return headercell
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 150
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.questionData?.questions[section].options.count ?? 0
}
func numberOfSections(in tableView: UITableView) -> Int {
return self.questionData?.questions.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let identifier = "Cell"
// Note, I have used force unwrapping and a forced downcast here as if either of these lines fail you have a serious problem and crashing is the simplest way of finding it during development
let option = self.questionData!.questions[indexPath.section].options[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath ) as! CellTableViewCell
cell.contentView.backgroundColor = .clear
cell.label.text = option
return cell
}
}
Если у вас работает этот базовый подход, вы можете попробовать добавить модель представления, если хотите.