Возникла проблема с динамической загрузкой данных в разделы UITableView
.Моим бизнес-требованием является то, что у меня есть ViewController
с именем "Courses", в этом представлении у меня есть tableView
с различными разделами, для которых я использовал TableViewHeaderFooterView
, для каждого заголовка у него будет соответствующее название курса, количество глав вэтот курс и количество заданий для этого курса, и я получаю все эти данные из вызова API. Я могу заполнить заголовки tableView
этими данными, а также я получу 'id' для каждого курса, который я добавил кактег для каждого заголовка.Теперь, когда я нажимаю на любой заголовок, я должен сделать еще один вызов API, отправив значение тега заголовка, который является courseID, поэтому я получу источник данных для tableView, и он должен расширить раздел с показом строк и данных.в строках, поступающих из источника данных.
Я могу сделать все это со статическими данными, где у меня есть источник данных, прежде чем нажать на заголовок, но я не знаю, как это сделать, если данные должнычтобы быть добавленным динамически при нажатии заголовков.
Я пытался сделать это, когда я нажимаю на любой заголовок в первый раз, он показывает данные для этого раздела, но если я нажимаю на тот же заголовокснова или любой другой заголовок Я получаю сбой с
Завершение приложения из-за необработанного исключения «NSInternalInconsistencyException», причина: «Неверное обновление: недопустимое количество строк в разделе 0. Количество строк, содержащихся всуществующий раздел после обновления (0) должен быть равен количеству строк, содержащихся в этом разделедо обновления (1), плюс или минус количество строк, вставленных или удаленных из этого раздела (0 вставлено, 0 удалено) и плюс или минус количество строк, перемещенных в или из этого раздела (0 перемещено, 0 перемещено).
Я публикую свои модели и код здесь:
Модель для названий курсов:
struct CourseNamesModel {
var courseName: String!
var courseNameLetter: String!
var numberOfChaptersAndAssignments: String!
var chapterCount: Int!
var courseId: Int!
var opened: Bool!
init(courseName: String, courseNameLetter: String, numberOfChaptersAndAssignments: String, chapterCount: Int, courseId: Int ,opened: Bool) {
self.courseName = courseName
self.courseNameLetter = courseNameLetter
self.numberOfChaptersAndAssignments = numberOfChaptersAndAssignments
self.chapterCount = chapterCount
self.courseId = courseId
self.opened = opened
}
}
Модельдля данных после нажатия на заголовок:
struct CourseDataModel {
var chapterName: String!
var documentAndAssignmentCount: String!
init(chapterName: String, documentAndAssignmentCount: String!) {
self.chapterName = chapterName
self.documentAndAssignmentCount = documentAndAssignmentCount
}
}
код для моего viewController и TableView
import UIKit
import Alamofire
class CoursesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, ExpandableHeaderViewDelegate {
@IBOutlet weak var tableView: UITableView!
var sectionData = [CourseNamesModel]()
var tableData = [CourseDataModel]()
var selectedIdexPath: IndexPath!
override func viewDidLoad() {
super.viewDidLoad()
self.setFontFamilyAndSize()
self.title = "Courses"
selectedIdexPath = IndexPath(row: -1, section: -1)
tableView.register(UINib(nibName: "ExpandableHeaderView", bundle: nil), forHeaderFooterViewReuseIdentifier: "expandableHeaderView")
getCourseNames()
}
func numberOfSections(in tableView: UITableView) -> Int {
return sectionData.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData.count
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return tableView.frame.size.height/8.2
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if sectionData[indexPath.section].opened {
return tableView.frame.size.height/8.48275862069
} else {
return 0
}
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 1
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "expandableHeaderView") as! ExpandableHeaderView
headerView.customInit(courseName: sectionData[section].courseName, letterSign: sectionData[section].courseNameLetter, numberOfChaptersAndAssignments: sectionData[section].numberOfChaptersAndAssignments, section: section, delegate: self)
headerView.tag = sectionData[section].courseId
return headerView
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "dataCell") as! DataCell
cell.chapterName.text = tableData[indexPath.row].chapterName
cell.numberOfDocumentsAndAssignments.text = tableData[indexPath.row].documentAndAssignmentCount
return cell
}
func getCourseNames() {
sectionData = []
let courseNamesURL = "\(WebAPI.baseURL2 + WebAPI.coursesAPI)"
Alamofire.request(courseNamesURL, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: nil).responseJSON { response in
switch response.result {
case .success:
let responseData = response.result.value as? [[String: Any]]
guard let courseNamesData = responseData else {return}
for courseDetail in courseNamesData {
let courseName = courseDetail["CourseName"] as! String
let courseNameLetter = String(courseName.first!)
let chaptersCount = courseDetail["Chapterscount"] as! Int
let assignmentsCount = courseDetail["AssignmentCount"] as! Int
let chaptersAndAssignemntsCount = "\(chaptersCount) Chapters, \(assignmentsCount) Assignments"
let courseId = courseDetail["CourseId"] as! Int
self.sectionData.append(CourseNamesModel(courseName: courseName, courseNameLetter: courseNameLetter, numberOfChaptersAndAssignments: chaptersAndAssignemntsCount, chapterCount: chaptersCount, courseId: courseId, opened: false))
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
case .failure(let error):
print(error.localizedDescription)
}
}
}
}
код для toggleSection (развернуть /Свернуть) Функция делегата:
func toggleSection(header: ExpandableHeaderView, section: Int) {
sectionData[section].opened = !sectionData[section].opened
tableData = []
let courseChaptersURL = "\(WebAPI.baseURL2 + WebAPI.courseChaptersAPI)\(header.tag)"
Alamofire.request(courseChaptersURL, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: nil).responseJSON {response in
switch response.result {
case .success:
let responseData = response.result.value as? [[String : Any]]
guard let courseChaptersData = responseData else {return}
for chapterDetail in courseChaptersData {
let chapterName = chapterDetail["ChapterName"] as! String
let documentsCount = chapterDetail["Documentscount"] as! Int
let assignmentsCount = chapterDetail["AssignmentCount"] as! Int
let documentsAndAssignmentsCount = "\(documentsCount) Documents, \(assignmentsCount) Assignments"
// let isMaterialPathDelete = chapterDetail["IsDeleteMaterialPath"] as! Bool
self.tableData.append(CourseDataModel(chapterName: chapterName, documentAndAssignmentCount: documentsAndAssignmentsCount))
}
print(self.tableData.count)
case .failure(let error):
print(error.localizedDescription)
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
tableView.beginUpdates()
tableView.endUpdates()
print("Selected Section Index is : \(section)")
}
Это все, что у меня есть, я пробовал это в течение последних 2 дней, я не могу понять это.