如何在UITableView中逐个显示嵌套API响应对象并切换节点
嵌套树形API响应的UITableView节点切换问题
已成功遍历到第一个嵌套API响应数组的末尾,但无法切换到下一个节点(例如从id为865的问题切换到id为866的问题)。尝试通过DFS遍历将JSON转为字典、参考CollectionView切换方案均无效,当前代码无法正确处理嵌套树形结构,需要实现在UITableView中逐个展示这些API响应对象并完成节点切换。
现有代码
DFS遍历代码
func preorderTraversalDFS(_ roots: [ResultsQuestions]?) -> [Int: TreeItem] { // Get the json response in dictionary guard let roots = roots else { return [:] } var result: [Int: TreeItem] = [:] for root in roots { let treeItem = TreeItem(id: root.id, title: root.title, description: root.description, type: root.type, assessment: root.assessment, choices: convertChoices(root.choices), choice: root.choice, creator: root.creator) result[root.id] = treeItem if let choices = root.choices { for choice in choices { let subTree = preorderTraversalDFS(choice.questions) subTree.forEach { (key, value) in result[key] = value } } } } arrayDict = result return result }
UITableView代理与数据源代码
extension viewController : UITableViewDelegate , UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return objResponseQuestions.count // decoded json stored in objResponseQuestions } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: nestedAssessmentTableViewCell.self), for: indexPath) as? nestedAssessmentTableViewCell else { return nestedAssessmentTableViewCell() } cell.selectionStyle = UITableViewCell.SelectionStyle.none cell.optionsLabel.text = objResponseQuestions?[indexPath.row].choices?[indexPath.row].title return cell } }
数据结构定义
// MARK: - Choice struct Choice: Codable { let id: Int let title: String let nasClass: String let question: Int let questions: [ResultsQuestions]? enum CodingKeys: String, CodingKey { case id, title case nasClass = "nasClass" case question, questions } } // MARK: - Result struct ResultsQuestions: Codable { let id: Int let title, description, type: String let assessment: Int let choices: [Choice]? let choice: Int? let creator: Int } // This is the data strut I have loaded my json response into
问题根源
- DFS遍历丢失树形关联:将所有节点存入字典后,无法追踪「选择某个选项后跳转至对应子节点」的关联关系,仅能获取孤立的节点数据。
- UITableView数据源未动态更新:直接使用原始的
objResponseQuestions作为数据源,无法根据用户的选择切换到下一层节点的内容。
解决方案
1. 维护当前节点与路径
在ViewController中添加变量记录当前展示的问题节点,以及路径(用于回退场景):
// 当前正在展示的问题节点 var currentQuestion: ResultsQuestions? // 问题路径栈,用于回退到上一层(可选) var questionPath: [ResultsQuestions] = []
2. 初始化初始节点
在视图加载完成后,设置初始展示的根节点:
override func viewDidLoad() { super.viewDidLoad() // 假设objResponseQuestions是根节点数组,取第一个作为初始节点 if let firstQuestion = objResponseQuestions?.first { currentQuestion = firstQuestion questionPath.append(firstQuestion) tableView.reloadData() } }
3. 修改UITableView代理与数据源
基于当前节点动态展示选项,并处理点击跳转逻辑:
extension ViewController: UITableViewDelegate, UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // 行数为当前节点的选项数量 return currentQuestion?.choices?.count ?? 0 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: NestedAssessmentTableViewCell.self), for: indexPath) as? NestedAssessmentTableViewCell else { return NestedAssessmentTableViewCell() } cell.selectionStyle = .none // 展示当前节点对应索引的选项标题 cell.optionsLabel.text = currentQuestion?.choices?[indexPath.row].title return cell } // 处理选项点击,切换到下一层节点 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { guard let selectedChoice = currentQuestion?.choices?[indexPath.row], let nextQuestions = selectedChoice.questions, let nextQuestion = nextQuestions.first else { // 无下一层节点时的逻辑(比如结束流程) return } // 更新当前节点并记录路径 currentQuestion = nextQuestion questionPath.append(nextQuestion) // 刷新表格展示新节点的选项 tableView.reloadData() } }
4. 可选:添加回退功能
如果需要支持返回上一层问题,可以添加按钮触发以下逻辑:
@IBAction func backButtonTapped(_ sender: UIButton) { guard questionPath.count > 1 else { // 已经是根节点,无法回退 return } // 移除当前节点,回到上一层 questionPath.removeLast() currentQuestion = questionPath.last tableView.reloadData() }
内容的提问来源于stack exchange,提问作者Kshitij876
相关产品推荐
相关产品推荐

